docs(02-08): complete dev-pair deploy, on-device re-measure, D-11 pass bar plan

This commit is contained in:
archipelago 2026-07-30 23:55:05 -04:00
parent f4ab25ef70
commit 2b89b78f18
4 changed files with 230 additions and 22 deletions

View File

@ -33,7 +33,7 @@ declared exit criteria (multinode pass + workstreams B/C/F), `.planning/codebase
- [x] **PERF-01**: The slowest tab switches and secondary-screen opens are profiled with causes named (remount storms, serial RPC waterfalls, uncached fetches) — fixes are targeted, not guessed
- [x] **PERF-02**: Main-tab switches render immediately from cached state with background refresh — no blank screens or long spinners on tabs already visited this session
- [ ] **PERF-03**: Secondary screens (screens reached from a tab's main page) open without a blocking full reload and are instant on repeat visits — verified on real node hardware, not just the dev box
- [x] **PERF-03**: Secondary screens (screens reached from a tab's main page) open without a blocking full reload and are instant on repeat visits — verified on real node hardware, not just the dev box
### Multinode Verification (MNODE)
@ -119,7 +119,7 @@ Which phases cover which requirements. Updated during roadmap creation.
| UIFIX-06 | Phase 1 | Pending |
| PERF-01 | Phase 2 | Complete |
| PERF-02 | Phase 2 | Complete (02-02 tracer + 02-04..02-07 extended KeepAlive/cache to every main tab, each dev-preview-verified against archi-dev-box per D-11) |
| PERF-03 | Phase 2 | Pending |
| PERF-03 | Phase 2 | Complete |
| MNODE-01 | Phase 3 | Pending |
| MNODE-02 | Phase 3 | Pending |
| MNODE-03 | Phase 3 | Pending |

View File

@ -82,7 +82,7 @@ Plans:
3. Secondary screens open without a blocking full reload; repeat visits are instant
4. The fixes are verified on real node hardware (not just the dev box) — the sluggishness the user reported is gone on-device
**Plans**: 7/8 plans executed
**Plans**: 8/8 plans executed
Plans:
**Wave 1**
@ -106,7 +106,7 @@ Plans:
**Wave 5** *(blocked on Wave 4 completion)*
- [ ] 02-08-PLAN.md — Dev-pair deploy, on-device re-measure, D-11 pass bar (PERF-01/02/03)
- [x] 02-08-PLAN.md — Dev-pair deploy, on-device re-measure, D-11 pass bar (PERF-01/02/03)
**UI hint**: yes
@ -205,7 +205,7 @@ Phases execute in numeric order: 1 → 2 → 3 → 4 → 5 → 6 → 7 → 8
| Phase | Plans Complete | Status | Completed |
|-------|----------------|--------|-----------|
| 1. Federation & Mesh Hardening | 0/10 | Planned | - |
| 2. UI Performance | 7/8 | In Progress| |
| 2. UI Performance | 8/8 | In Progress| |
| 3. Multinode Verification Pass | 0/TBD | Not started | - |
| 4. Lifecycle Perfection & Quadlet Default | 0/TBD | Not started | - |
| 5. Registry-Distributed Manifests | 0/TBD | Not started | - |

View File

@ -3,18 +3,18 @@ gsd_state_version: 1.0
milestone: v1.8.0
milestone_name: milestone
current_phase: 02
current_phase_name: ui-performance
status: executing
stopped_at: Completed 02-07-PLAN.md
last_updated: "2026-07-30T22:43:45.233Z"
status: completed
stopped_at: Completed 02-08-PLAN.md — Phase 02 (ui-performance) complete, 8/8 plans
last_updated: "2026-07-31T03:54:32.766Z"
last_activity: 2026-07-30
last_activity_desc: Phase 02 execution started
last_activity_desc: Phase 02 marked complete
progress:
total_phases: 8
completed_phases: 0
total_plans: 18
completed_plans: 7
percent: 0
total_phases: 9
completed_phases: 1
total_plans: 25
completed_plans: 13
percent: 11
current_phase_name: ui-performance
---
# Project State
@ -28,12 +28,12 @@ See: .planning/PROJECT.md (updated 2026-07-29)
## Current Position
Phase: 02 (ui-performance) — EXECUTING
Plan: 7 of 8
Status: Ready to execute
Last activity: 2026-07-30 — Phase 02 execution started
Phase: 02 — COMPLETE
Plan: 8 of 8
Status: Phase 02 complete
Last activity: 2026-07-30 — Phase 02 marked complete
Progress: [████░░░░░░] 39%
Progress: [█████░░░░░] 52%
## Performance Metrics
@ -59,6 +59,7 @@ Progress: [████░░░░░░] 39%
| Phase 02 P05 | 50min | 2 tasks | 8 files |
| Phase 02 P06 | 73min | 2 tasks | 7 files |
| Phase 02 P07 | 75min | 3 tasks | 5 files |
| Phase 02 P08 | ~190min | 3 tasks | 4 files |
## Accumulated Context
@ -103,6 +104,11 @@ Decisions are logged in PROJECT.md (10 locked ADRs in the `<decisions>` block +
- [Phase ?]: 02-07: AIUI source located mid-plan at git.tx1138.com/lfg2025/AIUI (base branch development, not stale main); AIUI-side D-14 commit 900c0b9 initially local-only (anonymous push 403) then pushed/merged upstream onto development by the orchestrator using a user-supplied write token
- [Phase ?]: 02-07: D-14a fixed via new ?chatExpanded param overriding chat.ts's chatCollapsed default (never persisted to localStorage); D-14b fixed via new ?mobileChat param re-asserting ChatPage.vue's mobileTab='chat' once on mount, guarding against module-singleton content-panel state surviving an internal AIUI remount
- [Phase ?]: 02-07: PERF-02 marked Complete in REQUIREMENTS.md — 02-02 through 02-07 extended KeepAlive/useCachedResource to every main tab, each dev-preview-verified against archi-dev-box per D-11
- [Phase ?]: 02-08: KEEP_ALIVE_MAX left at 6, now backed by an on-device memory reading (4 cycles, 11 tabs, JS heap fluctuating 10-21MB, no monotonic growth) rather than the FA-D estimate
- [Phase ?]: 02-08: archy-x250-dev offline for the entire plan (checked 3x); archi-dev-box (D-11's named target) is the only dev-pair node this phase reached
- [Phase ?]: 02-08: the harness's remount-probe field is confounded for main tabs once real KeepAlive keeps multiple instances alive simultaneously; corrected via an independent, reproduced-twice verification rather than editing the frozen 02-01 harness — revealed Server.vue genuinely does not survive a round-trip (open gap, not hidden)
- [Phase ?]: 02-08: a user-reported Cloud first-visit navigation regression was treated as release-blocking, not known-open, per explicit direction — root-caused to content.browse-peer's unbounded, untimed-enough per-peer RPC fan-out starving Chromium's connection pool; fixed via a concurrency cap + shortened timeout, verified 5/5, user-approved on-node
- [Phase ?]: 02-08: 4 other user-reported UX issues (Paid Files window.open, PiP not closing lightbox, missing loader on Paid Files item-open, PiP not surviving tab changes) classified as pre-existing (predate phase 2 via git history) and captured into UIFIX-04/05/06, not fixed
### Pending Todos
@ -122,6 +128,8 @@ Decisions are logged in PROJECT.md (10 locked ADRs in the `<decisions>` block +
- [Phase 6] Strengthened ADR-009 validation may reject existing catalog apps — audit manifests before enforcement lands
- [Global] Live OTA fleet: deploy to the dev pair before any OTA; gate re-runs required after orchestrator changes; some verification is user/hardware-gated (radios, on-device tests)
- cloud.ts's navigate() needs a TTL gate to fully satisfy 'no new RPC within TTL' for CloudFolder.vue — currently always re-fetches on revisit (just doesn't block paint)
- [Phase 2, carried forward] Server.vue does not survive a tab round-trip despite KEEP_ALIVE_PATHS registration — confirmed real gap, needs a future targeted fix
- [Phase 2, carried forward] Timing regressions on Discover/Web5/Fleet/AppDetails/OpenWrtGateway (02-PERF-AFTER.json vs baseline) — a same-time-of-day re-run would help disambiguate real regression from node-load noise
### Quick Tasks Completed
@ -143,6 +151,6 @@ Decisions are logged in PROJECT.md (10 locked ADRs in the `<decisions>` block +
## Session Continuity
Last session: 2026-07-30T22:43:45.214Z
Stopped at: Completed 02-07-PLAN.md
Last session: 2026-07-31T03:54:32.747Z
Stopped at: Completed 02-08-PLAN.md — Phase 02 (ui-performance) complete, 8/8 plans
Resume file: None

View File

@ -0,0 +1,200 @@
---
phase: 02-ui-performance
plan: 08
subsystem: ui
tags: [playwright, vue3, keepalive, performance-verification, connection-pool, real-hardware]
# Dependency graph
requires:
- phase: 02-ui-performance/02-01
provides: "The re-runnable surface-perf harness (neode-ui/e2e/perf/{surfaces,measure,surface-perf.spec}.ts) and the 02-PERF-BASELINE.json this plan re-runs against and compares to"
- phase: 02-ui-performance/02-02..02-07
provides: "The full KeepAlive + useCachedResource architecture (all main tabs, Mesh, Server/Home, Chat/AIUI) this plan deploys and measures on real hardware"
provides:
- "02-PERF-AFTER.json — the after-artifact from re-running the 02-01 harness unmodified against archi-dev-box"
- "02-FINDINGS.md Results/Outstanding sections — per-surface before/after comparison, with a documented remount-probe methodology correction"
- "KEEP_ALIVE_MAX confirmed at 6 via an on-device Chromium heap reading (FA-D closed)"
- "A real-hardware connection-pool-starvation defect found, root-caused, and fixed in Cloud.vue (content.browse-peer unbounded fan-out)"
- "The phase's own D-11 pass bar, human-approved on archi-dev-box"
affects: []
# Tech tracking
tech-stack:
added: []
patterns:
- "Concurrency-capped RPC fan-out (queue + worker pool, BROWSE_PEER_CONCURRENCY=3) mirroring PeerFiles.vue's existing PREVIEW_CONCURRENCY convention — the second instance of this pattern in the codebase, now established for any per-peer/per-item RPC fan-out"
- "Harness remount-probe correction: a generic rootSelector (.view-container) shared across every main tab becomes ambiguous once real KeepAlive keeps multiple instances alive simultaneously — verify by stamping/reading the VISIBLE match (getBoundingClientRect/offsetParent) rather than the first DOM match, since KeepAlive's inactive cached instances are not laid out on screen"
- "CDP Performance.getMetrics (JSHeapUsedSize) as the on-device memory-reading instrument for KEEP_ALIVE_MAX tuning, more reliable across Chromium variants than performance.memory"
key-files:
created:
- .planning/phases/02-ui-performance/02-PERF-AFTER.json
modified:
- .planning/phases/02-ui-performance/02-FINDINGS.md
- neode-ui/src/views/dashboard/keepAliveRoutes.ts
- neode-ui/src/views/Cloud.vue
key-decisions:
- "KEEP_ALIVE_MAX left at 6, now backed by measurement instead of estimate: 4 full two-way cycles through all 11 main tabs on archi-dev-box showed JS heap fluctuating 10-21MB with no monotonic growth trend, confirming the cap's eviction genuinely bounds memory rather than sitting unused against the 10 registered cache-eligible paths"
- "Deployed to archi-dev-box only (this machine, confirmed via Tailscale MagicDNS to be the same physical ThinkPad build server) — archy-x250-dev, the dev pair's second node, was offline for the entire plan (checked at Task 1, before Task 2, and again before the final redeploy; never came back). D-11's verification target is archi-dev-box specifically, so this satisfies the plan, but the second dev-pair node has received none of this phase's changes and needs the same --frontend-only deploy once it's reachable"
- "The harness's own remount-probe field is confounded for main tabs once real KeepAlive caching is active (multiple .view-container-classed instances coexist; document.querySelector's first-DOM-match can read/write the wrong one) — corrected independently via a harness-external, reproduced-twice verification rather than editing the frozen 02-01 harness; Home/Apps/Marketplace/Cloud/Web5/Fleet confirmed to genuinely survive a round-trip, Server confirmed to genuinely NOT (a real, open gap)"
- "A user-reported checkpoint regression (first visit to Cloud: no folder opens on click) was treated as a release-blocking defect, not a known-open item, per explicit coordinator direction — required two separate fix commits to fully close: a fresh-mount guard (necessary but insufficient) and a concurrency cap + timeout on content.browse-peer's per-peer fan-out (the actual mechanism: 13 of 14 concurrent RPCs to dead/unreachable peers never settled, starving Chromium's per-origin connection pool and silently breaking every subsequent same-origin fetch including lazy route-chunk imports)"
- "Four other user-reported UX issues (Paid Files opening in a new tab instead of the lightbox, PiP not closing the lightbox, a missing loader state on Paid Files' item-open RPC, PiP not surviving tab changes/buffering) were classified via git history against the pre-phase-2 baseline commit (a75b6709) and confirmed pre-existing, not phase-2 regressions — captured with file/line pointers into UIFIX-04/05/06 rather than fixed here, per the phase's own scope boundary and explicit coordinator direction not to implement fixes for pre-existing gaps"
requirements-completed: [PERF-01, PERF-02, PERF-03]
coverage:
- id: D1
description: "The 02-01 harness re-run unmodified against archi-dev-box produces a directly comparable after-artifact (02-PERF-AFTER.json), 15/15 rows matching the baseline's row count"
requirement: "PERF-01"
verification:
- kind: automated_ui
ref: "neode-ui/e2e/perf/surface-perf.spec.ts run against http://archi-dev-box, ARCHY_PERF_RUNS=3 — exit code 0, 15/15 rows written"
status: pass
human_judgment: false
- id: D2
description: "Every surface named as slow in the findings has a committed after-number and Verdict (improved/unchanged/regressed/unmeasured); no regression or unmeasured surface is averaged away or hidden"
requirement: "PERF-01"
verification:
- kind: other
ref: "02-FINDINGS.md ## Results table (15 rows, every Verdict cell populated) and ## Outstanding (every regression/gap explicitly listed)"
status: pass
human_judgment: false
- id: D3
description: "Every main tab registered in KEEP_ALIVE_PATHS is independently re-verified for genuine instance survival across a tab round-trip, correcting a harness-methodology confound discovered this run"
requirement: "PERF-02"
verification:
- kind: other
ref: "02-FINDINGS.md Results section — corrected remount verification reproduced twice per surface (Home/Apps/Marketplace/Cloud/Web5/Fleet survive; Server does not, recorded as an open gap, not hidden)"
status: pass
human_judgment: false
- id: D4
description: "KEEP_ALIVE_MAX is set from an observed on-device memory reading rather than an estimate, with the reading recorded"
requirement: "PERF-02"
verification:
- kind: other
ref: "neode-ui/src/views/dashboard/keepAliveRoutes.ts comment (4 cycles, 11 tabs, CDP JSHeapUsedSize: 8.8MB baseline, 10.02/20.69/16.67/14.12MB per cycle, no monotonic growth)"
status: pass
human_judgment: false
- id: D5
description: "The D-11 pass bar (no visible spinner/blank on revisit of an already-visited tab or secondary screen this session) is confirmed on archi-dev-box by a human, on real node hardware — including a real, user-reported regression found during the check being root-caused and fixed rather than shipped as known-open"
requirement: "PERF-03"
verification:
- kind: manual_procedural
ref: "Task 3 checkpoint:human-verify — first pass 'otherwise it's getting much better' plus 4 specific issues; the one release-blocking issue (Cloud first-visit folder-click) was fixed across two commits and the user's final re-check on archi-dev-box returned 'approved'"
status: pass
human_judgment: true
rationale: "Visual/perceptual confirmation of no-spinner/no-blank revisits and of the fix's real-world feel is inherently a human judgment call a script cannot make, consistent with every prior plan's D-11 checkpoint precedent in this phase."
duration: ~3h10min (includes one human-action checkpoint pause for the archi-dev-box credential, one human-verify checkpoint round-trip with two follow-up investigation/fix cycles)
completed: 2026-07-30
status: complete
---
# Phase 02 Plan 08: Dev-Pair Deploy, On-Device Re-Measure, D-11 Pass Bar Summary
**Deployed the full phase to archi-dev-box, re-measured every surface with the same harness and target as the baseline (uncovering and correcting a remount-probe confound the new KeepAlive architecture exposed), confirmed KEEP_ALIVE_MAX=6 from an on-device memory reading, and closed a real first-visit connection-pool-starvation regression found during the human pass bar — content.browse-peer's unbounded, untimed per-peer fan-out, not the router or the click handler.**
## Performance
- **Duration:** ~3h10min (Task 1 build+deploy+memory-tuning, a human-action checkpoint pause for the archi-dev-box password, Task 2 re-measurement, and a Task 3 checkpoint round-trip with two full investigation-and-fix cycles for a user-reported regression)
- **Completed:** 2026-07-30
- **Tasks:** 3/3 completed (Task 3 is the plan's checkpoint:human-verify, approved)
- **Files modified:** 3 (1 artifact created, 2 source files modified across 6 substantive commits)
## Accomplishments
- Deployed this phase's frontend (and confirmed AIUI's already-current `development`-branch build) to **archi-dev-box** via `ARCHIPELAGO_TARGET=archipelago@archi-dev-box scripts/deploy-to-target.sh --frontend-only` — this machine (the ThinkPad build server) is archi-dev-box itself, confirmed via Tailscale MagicDNS. `archy-x250-dev`, the dev pair's second node, was checked and found offline at three separate points across the plan and never came back; only archi-dev-box received this phase's build, which is what D-11 names as the verification target.
- Confirmed the built bundle was genuinely current (not a stale/no-op build) by grepping the **served** asset (`/opt/archipelago/web-ui`, not just the local `web/dist` copy) for representative strings from every plan in the phase.
- Tuned `KEEP_ALIVE_MAX` from a real on-device Chromium heap reading (CDP `Performance.getMetrics`) instead of leaving the carried-forward estimate unexamined: 4 full two-way cycles through all 11 main tabs showed the heap fluctuating 10-21MB with no monotonic growth — confirmed the cap at 6 is genuinely bounding memory, not sitting unused. Left unchanged, now measurement-backed.
- Re-ran the plan 02-01 harness **unmodified** against archi-dev-box, producing `02-PERF-AFTER.json` (15/15 rows, matching the baseline's row count) and appending `02-FINDINGS.md`'s `## Results`/`## Outstanding` sections.
- **Discovered and corrected a harness-methodology confound this run exposed for the first time**: the remount probe's generic `.view-container` selector — unambiguous pre-phase-2 when only one view was ever mounted — becomes ambiguous once real KeepAlive keeps multiple main-tab instances alive simultaneously. Rather than editing the frozen harness, independently re-verified every main tab's true remount status with a corrected, reproduced-twice method: Home/Apps/Marketplace/Cloud/Web5/Fleet genuinely survive a round-trip; **Server genuinely does not** — recorded as an open, unfixed gap rather than smoothed over.
- Recorded real timing regressions (Discover, Server, Web5, Fleet, AppDetails, OpenWrtGateway) honestly per the plan's own prohibition against averaging them away, with a same-time-of-day-variance caveat noted for interpretation, not used to soften any verdict.
- **Found, root-caused, and fixed a genuine real-hardware regression during the Task 3 checkpoint**: a user-reported "first visit to Cloud, no folder opens on click" was proven — via direct instrumentation (a raw DOM click listener, a patched live `$router` instance, request-lifecycle tracking, and manual `import()` calls from the page console) — to be a downstream symptom of Chromium's per-origin connection pool being starved by 13 of 14 concurrent, permanently-pending `content.browse-peer` RPCs to dead/unreachable peers, not a router or click-handler bug. Closed across two commits: a fresh-mount guard on `Cloud.vue`'s dual `onMounted`/`onActivated` fire (necessary but insufficient alone), then a concurrency cap (3) + shortened timeout (10s) on the peer-browse fan-out itself, mirroring `PeerFiles.vue`'s existing `PREVIEW_CONCURRENCY` pattern. Verified 5/5 fresh sessions navigate cleanly, zero in-flight hung requests after 15s on Cloud, and a previously-permanently-hung route chunk import now resolves in 17ms. User's final on-node re-check: **approved**.
- Classified four other user-reported UX issues via git history against the pre-phase-2 baseline commit (`a75b6709`) and confirmed all pre-existing, not phase-2 regressions, with exact file/line pointers captured into UIFIX-04/05/06 for phase 1's gap-closure work — no fixes implemented for these, per scope boundary and explicit direction.
## Task Commits
Each task was committed atomically (Task 3's checkpoint follow-up investigation produced additional fix/docs commits, listed under it):
1. **Task 1: Build and deploy the frontend to the dev pair only** - `3ee20430` (docs — KEEP_ALIVE_MAX confirmed via on-device memory reading; no code change needed since the constant stayed at 6)
2. **Task 2: Re-measure on archi-dev-box and write the before/after comparison** - `f1206ad6` (docs — 02-PERF-AFTER.json + FINDINGS.md Results/Outstanding)
3. **Task 3: D-11 pass bar checkpoint** - checkpoint:human-verify, first pass returned "otherwise it's getting much better" plus 4 specific issues; investigation and fixes landed as:
- `e1a3f31a` (fix — Cloud.vue fresh-mount guard; necessary, not sufficient alone)
- `834edd8c` (docs — checkpoint follow-up: triage of all 5 reported items, root cause instrumentation findings)
- `8fe6217b` (fix — content.browse-peer concurrency cap + timeout; the fix that actually closed the regression)
- `a0c58277` (docs — confirmation the fix is verified 5/5, mechanism closed)
- Final on-node re-check: **approved**
**Plan metadata:** (this commit) - `docs(02-08): complete dev-pair deploy, on-device re-measure, D-11 pass bar plan`
## Files Created/Modified
- `.planning/phases/02-ui-performance/02-PERF-AFTER.json` - After-artifact from re-running the 02-01 harness against archi-dev-box (15 rows, `commit: "3ee20430"`, `runs: 3`)
- `.planning/phases/02-ui-performance/02-FINDINGS.md` - `## Results` (per-surface baseline/after comparison + corrected remount verification), `## Outstanding` (every regression/gap/carried assumption), and a `## Addendum: Task 3 Checkpoint Follow-Up` documenting the full investigation and classification of all 5 user-reported items
- `neode-ui/src/views/dashboard/keepAliveRoutes.ts` - `KEEP_ALIVE_MAX` comment updated to record the on-device memory reading that justifies leaving it at 6 (FA-D closed)
- `neode-ui/src/views/Cloud.vue` - Fresh-mount guard on `syncOnEntry()` (matching Home/Web5/Mesh/Server's existing pattern) + `content.browse-peer` fan-out capped at 3 concurrent with a 10s per-call timeout (`BROWSE_PEER_CONCURRENCY`, `BROWSE_PEER_TIMEOUT_MS`, a queue/worker pool mirroring `PeerFiles.vue`'s `PREVIEW_CONCURRENCY` convention)
## Decisions Made
See `key-decisions` in frontmatter for the full list. Highlights:
- **KEEP_ALIVE_MAX stays 6**, now backed by a real on-device memory reading rather than the carried-forward FA-D estimate.
- **archi-dev-box only**`archy-x250-dev` was offline for the plan's entire duration (checked three times); recorded honestly rather than silently skipped, per D-11's specific naming of archi-dev-box as the verification target.
- **The harness's remount-probe field is unreliable for main tabs post-KeepAlive** — corrected via an independent, reproduced-twice verification method rather than editing the frozen 02-01 harness; the correction revealed Server.vue's genuine remount gap, which the raw (confounded) field would have hidden as "unchanged."
- **The Cloud first-visit regression was treated as release-blocking, not known-open**, per explicit coordinator direction — required isolating the true mechanism (an unbounded, untimed RPC fan-out to dead peers starving the browser's connection pool) rather than stopping at the first plausible-looking fix (the fresh-mount guard alone did not resolve it, and was honestly reported as insufficient before the real fix was found).
- **Pre-existing UX issues were classified, not fixed** — Paid Files' `window.open()` instead of the lightbox, PiP not closing the lightbox, a missing loader state on Paid Files' item-open, and PiP not surviving tab changes/buffering were all traced to commits predating phase 2 (`f3393581`, `f72d4b92`, both 2026-07-22/23, confirmed via `git merge-base --is-ancestor` against the `a75b6709` pre-phase-2 baseline) — captured into UIFIX-04/05/06 rather than fixed here, respecting this plan's own scope boundary.
## Deviations from Plan
### Auto-fixed Issues
**1. [Rule 1 - Bug, caught by the D-11 checkpoint] Cloud.vue's dual onMounted/onActivated fire doubled the first-activation request burst**
- **Found during:** Task 3 checkpoint, user-reported "first visit to Cloud, no folder opens on click"
- **Issue:** 02-04 exempted `Cloud.vue` from the fresh-mount guard pattern used elsewhere (Home/Web5/Mesh/Server), reasoning each individual resource is staleness/inflight-deduped. True per-resource, but the two back-to-back `onMounted`+`onActivated` passes still doubled `loadPeerFiles()`'s full per-peer RPC fan-out in the same tick on a component's first KeepAlive activation.
- **Fix:** Added the same fresh-mount guard (`cloudFreshMount`) already used in Home.vue/Web5.vue/Mesh.vue/Server.vue.
- **Files modified:** `neode-ui/src/views/Cloud.vue`
- **Verification:** Full suite green (95/774); reduced but did not eliminate the reported symptom — honestly reported as insufficient before proceeding to the real fix below.
- **Committed in:** `e1a3f31a`
**2. [Rule 1 - Bug, the actual root cause] content.browse-peer's unbounded, untimed-enough fan-out starved the browser's connection pool**
- **Found during:** Task 3 checkpoint follow-up, after fix #1 above did not resolve the reported regression
- **Issue:** Direct instrumentation (request-lifecycle tracking of every `content.browse-peer` call during a fresh Cloud mount) showed 13 of 14 concurrent calls never settling at all — `loadPeerFiles()` fanned these out with zero concurrency cap and a 30s per-call timeout. That many simultaneously-open, indefinitely-pending same-origin requests to dead/unreachable peers starved Chromium's per-origin connection pool, silently breaking every other same-origin fetch for the rest of the session, including the lazy route chunk any later folder/tab navigation needs. Confirmed not a test-harness artifact (reproduced in full Chromium, not just headless-shell) and not explained by raw concurrency alone (an artificial 30-request burst against the same endpoint, done outside Cloud.vue, completed in 179ms with zero hang).
- **Fix:** Capped the fan-out at 3 concurrent requests (`BROWSE_PEER_CONCURRENCY`, a queue/worker pool) and shortened each call's timeout from 30s to 10s (`BROWSE_PEER_TIMEOUT_MS`), mirroring `PeerFiles.vue`'s existing `PREVIEW_CONCURRENCY` pattern for the identical class of problem. A timed-out/failed peer already resolved silently (no throw, no toast) via `resources.ts`'s own error-state path — confirmed unchanged.
- **Files modified:** `neode-ui/src/views/Cloud.vue`
- **Verification:** Full suite green (95/774), type-check and build clean, `keepAliveTabs.test.ts` structural assertions untouched. 5/5 fresh browser sessions (brand-new context each run) navigated cleanly on the first folder click against the redeployed build; zero in-flight hung requests after 15s on Cloud (previously exactly one, permanently pending); a previously-permanently-hung lazy route chunk import resolved in 17ms. User's final on-node re-check: approved.
- **Committed in:** `8fe6217b`
---
**Total deviations:** 2 auto-fixed (both Rule 1 — real bugs found during this plan's own verification checkpoint, not pre-existing issues out of scope, since the phase's own lifecycle changes altered when this fan-out fires and turned a latent unbounded-RPC pattern into a deterministic first-visit navigation breaker).
**Impact on plan:** Both were necessary corrections directly implicated by this plan's own must-have truths (the D-11 pass bar) and explicit coordinator direction that a deterministic navigation breaker cannot ship as known-open. No scope creep — both fixes stayed within `Cloud.vue`, the file already central to this checkpoint's investigation.
## Issues Encountered
- **Authentication gate on Task 1/Task 2**: archi-dev-box's real UI password was needed to drive the Playwright harness and was not derivable from this environment (matching 02-01's precedent). Paused at a `checkpoint:human-action`; the coordinator supplied the password out-of-band, passed only via the `ARCHY_PASSWORD` environment variable at runtime, never written to any committed file.
- **A recurring auto-show engagement/feature-announcement modal** (the same class of overlay 02-01 documented as `CompanionIntroOverlay`) intermittently intercepted clicks during on-device testing across this plan's Playwright-driven diagnostics; worked around per-script with a dismiss-if-present check, never touched in application code (out of this plan's scope).
- **The node's disk usage is genuinely at 85% right now**, triggering a persistent `HealthNotifications.vue` toast that intercepted Chat's close button in this run (a different specific blocking cause than baseline's AIUI-connection-timeout reason, same "unmeasured" outcome for Chat). Flagged in `FINDINGS.md` as worth a follow-up fix (the toast's wrapper lacks `pointer-events: none`) independent of this phase.
## User Setup Required
None — no external service configuration required. archi-dev-box's real UI password, used to drive on-device verification, 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
- **PERF-01, PERF-02, and PERF-03 are all now genuinely complete** — PERF-03 specifically required real-node-hardware verification per its own requirement text, which this plan's Task 3 checkpoint (including the regression it caught and this plan closed) provides.
- **Open, non-blocking follow-ups carried forward** (all recorded in `02-FINDINGS.md`'s `## Outstanding`, none block this phase's completion per the user's own "otherwise much better" call):
- Server.vue does not survive a tab round-trip despite being registered in `KEEP_ALIVE_PATHS` — a real, confirmed gap needing a future targeted fix.
- Timing regressions on Discover/Web5/Fleet/AppDetails/OpenWrtGateway, recorded honestly with numbers; a same-time-of-day re-run would help disambiguate real regression from environmental (85%-disk, multi-service node) noise.
- `archy-x250-dev` has received none of this phase's changes — needs the same `--frontend-only` deploy once it's back online.
- `/dashboard/settings` remains withheld from `KEEP_ALIVE_PATHS` (02-04's own deliberate, unaudited-risk exclusion).
- `cloudStore.navigate()`'s residual TTL gap (02-03's known gap) and `PeerFiles.vue`'s non-`useCachedResource` fetch pattern (02-03's own flagged correction) remain open.
- UIFIX-04/05/06 now have exact file/line pointers for four pre-existing UX issues surfaced during this plan's checkpoint, ready for phase 1's gap-closure work.
- No blockers for the milestone's next phase.
---
*Phase: 02-ui-performance*
*Completed: 2026-07-30*
## Self-Check: PASSED
All claimed files found on disk (`02-PERF-AFTER.json`, `02-FINDINGS.md`, `keepAliveRoutes.ts`, `Cloud.vue`) and all claimed commits found in git history (`3ee20430`, `f1206ad6`, `e1a3f31a`, `834edd8c`, `8fe6217b`, `a0c58277`).