19 KiB
phase, plan, subsystem, tags, requires, provides, affects, tech-stack, key-files, key-decisions, patterns-established, requirements-completed, coverage, duration, completed, status
| phase | plan | subsystem | tags | requires | provides | affects | tech-stack | key-files | key-decisions | patterns-established | requirements-completed | coverage | duration | completed | status | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 02-ui-performance | 01 | ui |
|
|
|
|
|
|
|
|
|
~100min (includes one human-action checkpoint pause for the archi-dev-box credential) | 2026-07-30 | complete |
Phase 02 Plan 01: Surface Perf Harness & D-10 Findings Summary
Built a re-runnable Playwright perf harness, measured 13/15 D-09 surfaces on real archi-dev-box hardware, and committed the D-10 findings doc that names Marketplace (2033ms revisit) as the worst offender and the 02-02 tracer pick — while also confirming ContainerAppDetails.vue (RESEARCH.md's one "confirmed" serial-waterfall target) is fully unreachable dead code, leaving no live waterfall target in this phase.
Performance
- Duration: ~100 min total (includes a human-action checkpoint pause: the harness build/verify was quick, but Task 2 was blocked on the archi-dev-box UI password until the coordinator provided it)
- Completed: 2026-07-30
- Tasks: 3/3 completed
- Files modified: 5 created (3 harness files, 1 baseline artifact, 1 findings doc), 0 files modified under
neode-ui/src
Accomplishments
neode-ui/e2e/perf/{surfaces,measure,surface-perf.spec}.ts— a re-runnable Playwright harness covering all 10 D-09 primary surfaces (Home, Apps, Marketplace, Discover, Cloud, Mesh, Server, Web5, Fleet, Chat), 4 secondary screens (AppDetails, MarketplaceAppDetails, CloudFolder, OpenWrtGateway), and the located wallet-send flow (a modal on the Home wallet card — RESEARCH.md found noWallet.vue). Navigation is via real UI clicks (neverpage.gotobetween surfaces) so revisit timing reflects genuine Vue Router client-side transitions, not full page reloads..planning/phases/02-ui-performance/02-PERF-BASELINE.json— committed baseline taken against archi-dev-box (real node hardware, the D-11 verification target), 3 runs per surface. 13/15 surfaces measured cleanly; Mesh and Chat recorded unmeasured with specific, cited reasons..planning/phases/02-ui-performance/02-FINDINGS.md— the D-10 gate doc. Every row's Primary Cause cites a02-PERF-BASELINE.jsonfield. Key findings: 4 main tabs are already fast and left alone; Marketplace is the tracer pick for 02-02; no surface shows a serial-waterfall signature; a measurement confound (RPC bleed-through from an intermediate main-tab hop in 3 rows' nav chains) is documented rather than masked; Wallet-send's revisit being slower than its first visit is flagged as a genuine anomaly for 02-03 to profile directly.
Task Commits
Each task was committed atomically:
- Task 1: Build the re-runnable surface perf harness -
a75b6709(feat) - Task 2: Record the on-device baseline from archi-dev-box -
36145140(fix — includes the baseline artifact plus harness hardening discovered while running it against real hardware) - Task 3: Write and commit the D-10 findings doc -
675deb65(docs)
No separate plan-metadata commit was made for this SUMMARY — this file, STATE.md, and ROADMAP.md are committed together in the final commit below.
Files Created/Modified
neode-ui/e2e/perf/surfaces.ts- SURFACES table: one row per D-09 surface + secondary screens + wallet-send, with real-clicknavSteps,contentSelector,rootSelectorneode-ui/e2e/perf/measure.ts-measureSurface(): first-visit/revisit timing, RPC trace, remount probe, sweep-line concurrency derivation, dismiss-and-retry overlay guardneode-ui/e2e/perf/surface-perf.spec.ts- Playwright spec: logs in via the existingapp-launch.spec.tsflow, walks every surface, writes the JSON artifact.planning/phases/02-ui-performance/02-PERF-BASELINE.json- Committed on-device baseline (archi-dev-box, 3 runs/surface).planning/phases/02-ui-performance/02-FINDINGS.md- D-10 findings doc: per-surface cause table, ranked fix order, surfaces left alone, corrections to prior research, owning-plan map
Decisions Made
- Marketplace is the 02-02 tracer tab — worst-measured main tab (2033ms revisit) and matches the user's specific complaint ("often app store").
- No serial-RPC-waterfall Primary Cause was assigned anywhere — every surface with 2+ RPC calls on revisit showed
maxConcurrentRpcat or near its total call count (already parallel).ContainerAppDetails.vue, RESEARCH.md's one confirmed waterfall target, is confirmed unreachable dead code this session (grep -rn "ContainerAppDetails" neode-ui/srcreturns nothing — no importer, no route entry). - 3 rows' RPC evidence is flagged as confounded, not silently trusted: Marketplace, MarketplaceAppDetails, and OpenWrtGateway all reach their target via a
navStepschain that transits another main tab first (Home or Server), whose ownonMountedRPC burst is still resolving when the harness's tracker starts recording — captured method names for OpenWrtGateway are an exact subset of Server.vue's own known call set, confirming the confound rather than assuming it. These rows are classified conservatively (remount storm) with the confound spelled out for 02-02/02-03 to re-verify with DevTools. - Home, Apps, Cloud, Fleet are left alone (D-02) — all measured sub-500ms revisit with 0-1 trivial RPC calls; no
useCachedResourceconversion planned for their data layer, only the shared<KeepAlive>wrapping from 02-04. - Wallet-send's anomaly (revisit consistently slower than first-visit, 2607ms vs 735ms median, across all 3 runs) is flagged explicitly rather than smoothed over, since it has zero RPC either time and needs direct DevTools profiling in 02-03 to explain.
- Auth gate handled via checkpoint, not guessed: archi-dev-box's real UI password was unknown and not discoverable from this environment (checked
scripts/deploy-config.sh— gitignored, not present on this machine; no plaintext credential found via SSH). Rather than falling back to the mock-backend baseline silently or guessing a password, the plan paused at acheckpoint:human-actionand resumed once the coordinator supplied the credential. The password itself was never written to any committed file — passed only via theARCHY_PASSWORDenvironment variable at runtime.
Deviations from Plan
Auto-fixed Issues
1. [Rule 1 - Bug] Cascading harness failures from an unhandled Companion-app auto-show overlay
- Found during: Task 1 verification (local mock-backend run)
- Issue: A once-per-browser Companion-app intro overlay (
CompanionIntroOverlay.vue, opened viauseCompanionIntro's auto-show gate) can appear mid-click on the Home page, intercepting every subsequent sidebar click for the rest of the run — one surface's stray UI cascaded failures into every remaining surface. - Fix: Added
dismissOverlays()(Escape key + any[aria-label*="Close" i]button inside a dialog/full-screen overlay) called before every navigation click, wrapped in aclickWithGuard()retry loop (3 attempts, dismissing between each) since the overlay can appear after the initial dismiss check but before Playwright's own actionability wait resolves. - Files modified:
neode-ui/e2e/perf/measure.ts - Verification: Re-ran the harness against the mock backend; surfaces after the overlay's first appearance (previously 100% failure) measured cleanly.
- Committed in:
a75b6709(Task 1 commit)
2. [Rule 1 - Bug] Fleet's "Fleet" link selector matched a CSS-hidden duplicate
- Found during: Task 1 verification
- Issue:
Web5Federation.vuerenders two "Fleet"RouterLinks — one inside.web5-card-actions-top(permanentlydisplay: noneper a project-wide "compact header variants are retired" CSS rule) and the real, visible one inside.web5-card-actions-bottom-grid.a:has-text("Fleet")with.first()matched the hidden copy. - Fix: Scoped the selector to
.web5-card-actions-bottom-grid a:has-text("Fleet"). - Files modified:
neode-ui/e2e/perf/surfaces.ts - Verification: Fleet measured cleanly in the next mock-backend run.
- Committed in:
a75b6709(Task 1 commit)
3. [Rule 1 - Bug] Chat's hidden sidebar broke every subsequent surface's recovery navigation
- Found during: Task 1 verification, then again (worse) against real archi-dev-box hardware in Task 2
- Issue:
DashboardSidebar.vueisv-show="!chatFullscreen"— once on/dashboard/chat, the sidebar (and the neutral Settings link every other surface's "away" step and every surface'sgoHome()depend on) is invisible. On real hardware, AIUI's own "connecting" overlay could also outlive the harness's close-button click budget, leaving the run permanently stuck on Chat with a hidden sidebar and no way back — every surface measured after Chat failed. - Fix: Gave Chat its own
closeSelector(.chat-close-btn, which callscloseChat()'srouter.back()) instead of the generic Settings-tab away-step. Added a hardpage.goto('/dashboard')recovery fallback insidegoHome()for the case where even the close button is unreachable — an explicit, narrowly-scoped exception to the "nopage.gotobetween surfaces" rule, used only to break out of a stuck state, never to measure one. - Files modified:
neode-ui/e2e/perf/surfaces.ts,neode-ui/e2e/perf/measure.ts - Verification: Re-ran against archi-dev-box; all surfaces after Chat (previously cascading to 100% failure) measured cleanly, while Chat itself remains honestly recorded as unmeasured (AIUI's real connection latency exceeds the harness's budget on this hardware — a genuine finding, not a harness bug).
- Committed in:
36145140(Task 2 commit)
4. [Rule 1 - Bug] dismissOverlays() prematurely closed the exact dialog a closeSelector step meant to close
- Found during: Task 1 verification
- Issue:
dismissOverlays()treats any[aria-label*="Close" i]button inside a dialog as a stray overlay to dismiss. When the away-step's own deliberate close click (surface.closeSelector) was routed through the sameclickWithGuard()helper,dismissOverlays()closed the modal a beat before the explicit click ran, leaving that click with nothing to find (0 matches, immediate failure) for both Wallet-send and Chat. - Fix: The
closeSelectoraway-step click is a plainpage.locator(...).click(), not routed throughclickWithGuard/dismissOverlays. - Files modified:
neode-ui/e2e/perf/measure.ts - Verification: Wallet-send and Chat's away-steps stopped failing on a 0-match locator.
- Committed in:
a75b6709(Task 1 commit)
5. [Rule 1 - Bug] Run header's commit field always recorded 'unknown'
- Found during: Task 2, comparing the baseline artifact's header against Task 2's own acceptance criteria (
baseUrl,takenAt,commit,runs,notesmust all be recorded) - Issue:
currentCommit()shelled out togit rev-parse --short HEADusing{ cwd: __dirname }, but__dirnameis unavailable underneode-ui's"type": "module"ESM runtime — the resultingReferenceErrorwas silently swallowed by the existing catch block, always yielding'unknown'. - Fix: Use
process.cwd()instead (Playwright always sets this to the project root it was invoked from). - Files modified:
neode-ui/e2e/perf/surface-perf.spec.ts - Verification: Re-ran against archi-dev-box; the artifact's header now records the real short commit hash (
a75b6709). - Committed in:
36145140(Task 2 commit)
Total deviations: 5 auto-fixed (all Rule 1 — bugs found and fixed during the harness's own verification passes, not scope creep against the plan's task boundaries).
Impact on plan: All five were necessary for the harness to actually produce a trustworthy, non-cascading, correctly-labeled baseline. None touched neode-ui/src.
Issues Encountered
- Authentication gate on Task 2: archi-dev-box's real UI password was unknown and not derivable from this environment (the standard dev/test password used elsewhere in the repo,
password123, was rejected). Checked for a scripted credential (scripts/deploy-config.sh, gitignored, documented byscripts/deploy-config.example) — the actual file doesn't exist on this machine (likely lives on the ThinkPad build server per project memory). Stopped and returned acheckpoint:human-actionrather than falling back to a mock-backend baseline silently or attempting to reset the node's stored credential (out of scope, and risky on a shared dev node). The coordinator supplied the real password; execution resumed immediately and completed Tasks 2–3 without further blockers. - Measurement confound discovered and documented, not hidden: while writing the findings doc, comparing captured RPC method names across surfaces revealed that 3 rows' navigation chains transit another main tab before reaching their target, causing that intermediate tab's own
onMountedRPC burst to be misattributed to the destination surface. Rather than presenting the raw (confounded) RPC counts as clean "uncached fetch" evidence — which the plan's own prohibitions explicitly forbid ("MUST NOT present inferred, code-read, or cherry-picked numbers as measured profiling results") — those 3 rows were reclassified conservatively and the confound spelled out for downstream plans.
User Setup Required
None — no external service configuration required. The archi-dev-box password used for this run was supplied out-of-band by the coordinator and passed only via the ARCHY_PASSWORD environment variable at runtime; it is not stored in any file in this repository.
Next Phase Readiness
.planning/phases/02-ui-performance/02-FINDINGS.mdis committed and ready for 02-02 through 02-08 to consume — each has a clear owning-plan assignment, a cited Primary Cause, and (where applicable) an explicit measurement caveat to re-verify before implementing.- The harness (
neode-ui/e2e/perf/) is re-runnable as-is for 02-08's after-artifact comparison pass — no changes needed for that later plan to reuse it against the same archi-dev-box target. - Two open items carry forward: Mesh needs its own on-node profiling pass during 02-05 (this session's device-not-connected timeout may not reflect steady-state behavior); Chat's AIUI connection latency on real hardware (long enough to block even the close-button click) is itself a data point worth 02-07 investigating directly, separate from the two small D-14 UX defaults already scoped there.
Phase: 02-ui-performance Completed: 2026-07-30