docs(02): re-verification after gap closure

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
archipelago
2026-07-31 07:10:32 -04:00
co-authored by Claude Opus 5
parent 5fc3284a57
commit afc17c4e43
@@ -1,35 +1,35 @@
---
phase: 02-ui-performance
verified: 2026-07-31T00:00:00Z
verified: 2026-07-31T12:00:00Z
status: gaps_found
score: 6/8 must-haves verified
score: 5/8 must-haves verified
behavior_unverified: 0
overrides_applied: 0
re_verification:
previous_status: gaps_found
previous_score: 6/8
gaps_closed:
- "Gap 1: Server.vue (and, discovered mid-investigation, Web5.vue) KeepAlive remount — 02-09 proved with a corrected, authoritative document.elementFromPoint() hit-test signal (four independent device runs, zero contradicting readings) that the original 'genuinely remounts' finding was a probe-measurement artifact of the generic .view-container selector, not a real defect. Pinned with four vm.$.uid-based regression tests (re-run and confirmed green in this pass: 16/16 tests in keepAliveLifecycle.test.ts). keepAliveTabs.test.ts confirmed byte-for-byte unmodified. User confirmed on real hardware (Task 3 checkpoint, approved)."
gaps_remaining:
- "Gap 2: Timing regressions. Where the previous pass left this ambiguous ('regressed or unchanged... plausible candidate for environmental-noise'), 02-10's three-way re-measure (5 runs/surface, dispersion not medians, taken across three different days with disk pressure genuinely improving) has now CONFIRMED five of the six named surfaces as real, monotonically-worsening, phase-2-caused regressions — not noise. This makes the must-have's failure more certain, not less. None of the five is fixed; each is recorded as an 'accepted deviation' due to an operational deploy-safety blocker (shared-tree hazard), not a stakeholder decision that the regression is an acceptable outcome for this phase's own stated goal."
regressions: []
gaps:
- truth: "Every main tab registered for instance caching (KEEP_ALIVE_PATHS) genuinely survives a tab round-trip — the after-artifact's remount probe shows the component instance survived"
status: partial
reason: "02-08's own honest, independently-reproduced-twice remount probe (02-FINDINGS.md ## Results) confirms Home, Apps, Marketplace, Cloud, Web5 and Fleet genuinely survive a round-trip — but Server.vue, also registered in KEEP_ALIVE_PATHS since 02-04, genuinely does NOT (fully remounts on every revisit). This is a direct, self-admitted violation of 02-08-PLAN.md's own must-have truth, not a measurement artifact: it was reproduced twice specifically to rule out a fluke."
artifacts:
- path: "neode-ui/src/views/Server.vue"
issue: "Registered in KEEP_ALIVE_PATHS (via keepAliveRoutes.ts/TAB_ORDER) but its component instance is destroyed and recreated on every tab revisit; revisit ms also regressed (738ms baseline -> 849ms after) despite its own RPC count dropping (8 -> 2 via useCachedResource)."
missing:
- "Root-cause why Server.vue's KeepAlive wrapper registration doesn't actually keep its instance alive (02-FINDINGS.md explicitly defers this: 'Root cause not investigated here — Task 2's scope is measurement, not per-view debugging') and land a targeted fix, or an explicit accepted override if the team judges the current behavior (fast repopulate via cached RPCs, just not instance-preserving) good enough."
- truth: "For every surface the findings doc named as slow (pre-fix), the after-fix measurement shows a lower revisit time and a lower revisit RPC count than the baseline"
status: partial
reason: "02-08-PLAN.md's own must-have requires improvement on both dimensions for every previously-slow surface. 02-FINDINGS.md's ## Results table (self-reported, not inferred) shows 6 of ~9 measurable named-slow surfaces regressed or stayed flat on revisit ms even where RPC count improved: Discover (1083->1257ms, RPC unchanged 1->1), Server (738->849ms, RPC improved 8->2), Web5 (566->709ms, RPC unchanged 0->0), AppDetails (1204->1510ms, RPC improved 2->1), OpenWrtGateway (663.5->1148ms, RPC improved 4->2), and Wallet/send-flow (2607->2556ms, essentially unchanged, never touched by any plan's files_modified per the findings doc's own admission). Marketplace, MarketplaceAppDetails and CloudFolder did improve cleanly."
- truth: "For every surface the findings doc named as slow (pre-fix), the after-fix measurement shows a lower revisit time AND a lower revisit RPC count than the pre-phase-2 baseline"
status: failed
reason: "02-10's three-way re-measure (02-PERF-BASELINE.json / 02-PERF-AFTER.json / 02-PERF-REMEASURE.json, dispersion across n=3/3/5 samples) confirms — with zero sample-range overlap in the strongest case (Web5) and 4-of-5 samples outside the baseline range in the others — that Discover, Server, Web5, AppDetails and OpenWrtGateway are all REAL regressions, not measurement noise or a since-cleared confound. Medians climbed on every one of three independent runs, taken on three different days, even as the shared node's disk pressure genuinely eased (85% -> 79% free) — the opposite of what an environmental-noise explanation predicts. RPC counts flat-or-improved for all five, but the wall-clock time to visible content (the harness's own field definition: 'ms from the click that starts navigation to the surface's contentSelector becoming visible') got worse, in several cases dramatically: Web5 566->1329ms (+135%), AppDetails 1204->2668ms (+122%), OpenWrtGateway 663.5->1460ms (+120%), Server 738->1239ms (+68%), Discover 1083->1453ms (+34%), plus the out-of-named-scope bonus Fleet 330->2631ms (+697%, ~8x). These are not new/unrelated surfaces — they are core main tabs (Server, Web5) and secondary screens (AppDetails, OpenWrtGateway) that are the direct subject of PERF-02/PERF-03, now measurably slower on revisit than before this phase touched them at all."
artifacts:
- path: ".planning/phases/02-ui-performance/02-FINDINGS.md"
issue: "## Outstanding section documents these regressions honestly but no plan in this phase, and no later roadmap phase, closes them."
issue: "`## Re-measurement (gap closure)` section names the cause (client-side Vue-reactivity/re-render cost from the useCachedResource/KeepAlive conversion itself, exceeding the network time it eliminated) and traces it to specific phase-2 commits via git-log bisection against pre-phase-2 baseline a75b6709 — but records it under `### Accepted deviations` rather than fixing it. The plan's own intended 'fix it' branch (small, single-file, test-covered, deploy-and-re-measure) was never attempted this session because a concurrent session's uncommitted work in the shared neode-ui/src tree made a second deploy unsafe — an operational blocker, not evidence the fix is infeasible or that the regression is an acceptable trade-off."
missing:
- "Either a targeted investigation/fix for the regressed surfaces (FINDINGS.md itself suggests a same-time-of-day re-run to separate real regression from the node's 85%-disk/shared-build-server load noise it flags as a confound), or an explicit accepted override given the extensive human D-11 walkthrough already covered these exact tabs and secondary screens and returned 'approved'."
- "Either: (a) a targeted DevTools Performance-panel profiling pass identifying the specific reactivity/re-render cost per surface, a small fix, a clean deploy window (once the concurrent shared-tree sessions land), and a re-measure proving the number moved back toward or below baseline for Discover/Server/Web5/AppDetails/OpenWrtGateway; or (b) an explicit, accountable stakeholder decision (not the executing agent's own call under a deploy blocker) that shipping this phase with these five surfaces measurably slower than before the phase started is an acceptable trade-off for now — recorded as a formal override in this file's frontmatter with accepted_by/accepted_at, not merely as a findings-doc note."
deferred: []
human_verification:
- test: "Re-check Server.vue specifically: does a tab-switch away and back to Server show a visible spinner or blank frame on real archi-dev-box hardware, given it fully remounts but its RPC count is now only 2 (down from 8)?"
expected: "No visible spinner/blank frame — this is the literal PERF-02/D-11 pass bar, which is a lower bar than 'instance survives' and may already be met even though the stricter must-have failed"
why_human: "The Task 3 D-11 checkpoint walkthrough included Server in its tab-cycling steps and returned 'approved,' but the checkpoint transcript does not record the reviewer's attention being drawn to the specific Server remount finding (which was written up in FINDINGS.md's Results section, produced by Task 2, before Task 3's human pass) — worth an explicit confirmation that the approval covered this specific tab's current behavior, not just the general 'much better' impression."
- test: "Confirm whether the timing regressions on Discover/Web5/AppDetails/OpenWrtGateway are real code-caused regressions or same-node/time-of-day environmental noise, per FINDINGS.md's own caveat (baseline taken 10:30 local, after-run taken 01:27 next day on the same 85%-disk multi-service node)"
expected: "A same-time-of-day re-run of the harness would separate signal from noise"
why_human: "Requires scheduling a controlled re-run against archi-dev-box, which is outside static-analysis verification"
- test: "With a stopwatch/attention specifically on Discover, AppDetails and OpenWrtGateway (not just Server/Web5, which 02-09's checkpoint did cover), revisit each after having visited once this session and judge whether a ~1.5-2.7 second wait for content to appear reads as 'prompt' or as a felt stall, on archi-dev-box."
expected: "Either the wait is imperceptible in practice (e.g., a stale-cache paint happens well before the harness's stricter contentSelector-visible threshold, so the measured number overstates what a user actually experiences), or it is felt as a real delay — this needs a human's attention on exactly these three surfaces, since no checkpoint transcript in this phase's artifacts records a reviewer's attention being drawn to them specifically after 02-10's regression was confirmed."
why_human: "02-09's Task 3 checkpoint targeted Server/Web5 (remount/spinner/margins/transitions) specifically and returned approved for those; it did not include Discover, AppDetails or OpenWrtGateway, and 02-10 (an autonomous, non-checkpointed plan) produced no human read on whether its own confirmed regressions are perceptible."
- test: "Decide, as the accountable stakeholder, whether to accept the five confirmed timing regressions (Discover/Server/Web5/AppDetails/OpenWrtGateway, all measurably worse than pre-phase-2 baseline, none fixed) as a scoped-out follow-up so Phase 2 can be marked complete now, or to require a fix-and-reverify pass before closing the phase."
expected: "An explicit decision, recorded either as a formal override in this VERIFICATION.md (if accepting) or as a new gap-closure plan targeting these five surfaces (if not)."
why_human: "This is a phase-goal-level trade-off ('the UI feels fast' vs. a documented, unfixed regression in exactly the surfaces the phase targeted) that the executing agent is not positioned to accept on the project's behalf — the agent's own 'accepted deviation' framing in 02-FINDINGS.md was forced by an operational blocker (shared-tree deploy safety), not chosen as a considered scope decision."
---
# Phase 2: UI Performance Verification Report
@@ -37,7 +37,7 @@ human_verification:
**Phase Goal:** The UI feels fast — switching tabs and opening secondary screens renders promptly instead of stalling on refetches and remounts.
**Verified:** 2026-07-31
**Status:** gaps_found
**Re-verification:** No — initial verification
**Re-verification:** Yes — after gap closure (02-09, 02-10)
## Goal Achievement
@@ -45,72 +45,77 @@ human_verification:
| # | Truth | Status | Evidence |
|---|-------|--------|----------|
| 1 | The slowest tab switches and secondary-screen opens are profiled with causes named (remount storms, serial RPC waterfalls, uncached fetches), before any fix lands | ✓ VERIFIED | `02-FINDINGS.md` names a primary cause per D-09 surface, cites `02-PERF-BASELINE.json` fields for each, and was committed (`675deb65`) before the first `neode-ui/src` change in the phase (`385c9d86`) confirmed via `git log` ordering |
| 2 | Main-tab switches render immediately from cached state with background refresh — no blank screens/long spinners on tabs already visited this session | ⚠️ PARTIAL | 6 of 8 measured main tabs (Home, Apps, Marketplace, Cloud, Web5, Fleet) independently confirmed to genuinely survive a round-trip (reproduced twice); **Server.vue registered for instance caching but confirmed to genuinely remount on every revisit** (regression, not artifact — see gap 1). Mesh and Chat remain unmeasured both before and after (environmental blockers: device not reporting `connected`; a disk-usage toast intercepting the close button) — not evidence of failure but not evidence of success either |
| 3 | Secondary screens open without a blocking full reload and repeat visits are instant | ⚠️ PARTIAL | AppDetails, MarketplaceAppDetails, CloudFolder and OpenWrtGateway all converted to per-item keyed `useCachedResource` (no blocking reload, confirmed by code + tests); but repeat-visit **timing regressed** for AppDetails and OpenWrtGateway despite fewer RPCs, and the Wallet/send-flow anomaly (revisit slower than first visit, flagged in the 02-01 baseline) was never addressed by any plan's `files_modified` — see gap 2 |
| 4 | The fixes are verified on real node hardware (not just the dev box) — the sluggishness the user reported is gone on-device | ✓ VERIFIED | 02-08's `checkpoint:human-verify` (Task 3) walked every main tab and several secondary screens on archi-dev-box; first pass reported a real regression (Cloud first-click) which was root-caused (unbounded `content.browse-peer` fan-out starving the connection pool) and fixed across two commits, verified 5/5 fresh sessions; user's final re-check: **approved** |
| 5 | (02-08 must-have) Every main tab registered for instance caching survives a tab round-trip in the after-artifact's remount probe | ✗ FAILED | `02-FINDINGS.md` ## Results — Server.vue does not survive, confirmed via two independent reproductions of a corrected, harness-independent probe |
| 6 | (02-08 must-have) Every surface named as slow in the findings has a lower revisit time AND lower revisit RPC count after the fix | ✗ FAILED | 6 of ~9 named-slow surfaces regressed or stayed flat on revisit ms (Discover, Server, Web5, AppDetails, OpenWrtGateway, Wallet/send-flow); documented honestly in `02-FINDINGS.md` ## Results / ## Outstanding, not hidden |
| 7 | The instance-cache cap (`KEEP_ALIVE_MAX`) is set from observed on-device memory rather than an estimate | ✓ VERIFIED | `neode-ui/src/views/dashboard/keepAliveRoutes.ts` comment records a CDP `Performance.getMetrics` reading across 4 full cycles of all 11 main tabs (8.8MB baseline, 10-21MB range, no monotonic growth) |
| 8 | The build shipped to the dev pair contains this phase's changes, deployed only to the dev pair (no fleet/OTA) | ✓ VERIFIED | 02-08-SUMMARY.md records grepping the served bundle at `/opt/archipelago/web-ui` for representative strings; `archy-x250-dev` confirmed offline throughout (checked 3x), only `archi-dev-box` received the build — matches D-15/D-11 scope |
| 1 | The slowest tab switches and secondary-screen opens are profiled with causes named, before any fix lands | ✓ VERIFIED | Unchanged from initial pass — `02-FINDINGS.md` committed (`675deb65`) before the first `neode-ui/src` change (`385c9d86`), confirmed via `git log` ordering |
| 2 | Main-tab switches render immediately from cached state with background refresh — no blank screens/long spinners on tabs already visited this session | ✗ FAILED (downgraded from ⚠️ PARTIAL) | Server and Web5 — both main tabs — are now CONFIRMED (02-10, three-way dispersion, zero range overlap for Web5) to take 1.2s (Server) and 1.3s (Web5) median wall-clock time for content to become visible on revisit, up from 738ms/566ms before this phase started. This is not a remount (02-09 proved instance survival with an authoritative hit-test signal) but it is a real, measured stall against this truth's own "renders immediately" / "no long spinners" language |
| 3 | Secondary screens open without a blocking full reload and repeat visits are instant | ✗ FAILED (downgraded from ⚠️ PARTIAL) | AppDetails (1204→2668ms median) and OpenWrtGateway (663.5→1460ms median) are CONFIRMED real, phase-2-caused regressions by 02-10's three-way re-measure, both now well past 1 second and both worse than their pre-phase-2 baseline by more than 2x. Not "instant" by any reading of the word |
| 4 | The fixes are verified on real node hardware — the sluggishness the user reported is gone on-device | ⚠️ PARTIAL | The specific issues the user's checkpoints surfaced (Cloud first-click connection-pool starvation, Server/Web5 KeepAlive remount) were root-caused, fixed, and confirmed on-device. But the broader claim is contradicted by 02-10's confirmed, unfixed timing regressions across 5 surfaces, none of which were part of any human checkpoint's specific attention (see human_verification below) |
| 5 | (02-08/09 must-have) Every main tab registered for instance caching genuinely survives a tab round-trip | ✓ VERIFIED (flipped from ✗ FAILED — gap 1 closed) | 02-09's `keepalive-remount-probe.spec.ts`, run this session against the current `keepAliveLifecycle.test.ts` (16/16 tests green, including the 4 new `vm.$.uid`-based instance-identity tests added for this gap closure — re-run directly during this verification, not taken on trust), proves Server's and Web5's instances survive; the original "remounts" reading was a probe-selector artifact, independently confirmed via `document.elementFromPoint()` hit-testing across 4 device runs with zero contradicting readings |
| 6 | (02-08/09 must-have) Every surface named as slow has a lower revisit time AND lower revisit RPC count after the fix, vs. pre-phase-2 baseline | ✗ FAILED (still failed — now confirmed with certainty, not ambiguous) | 02-10's three-way re-measure resolves the "is this noise?" question the initial verification left open: 5 of 6 named surfaces (all but Wallet/send-flow, which cleared as noise) are confirmed real, monotonically-worsening regressions across 3 independent runs on 3 different days, even as the shared node's disk pressure genuinely improved between runs (85%→79% free) — the opposite of what noise would produce |
| 7 | The instance-cache cap (`KEEP_ALIVE_MAX`) is set from observed on-device memory rather than an estimate | ✓ VERIFIED | Unchanged from initial pass; 02-09's Test 4 re-confirms the cap is untouched by the gap-closure work |
| 8 | The build shipped to the dev pair contains this phase's changes, deployed only to the dev pair (no fleet/OTA) | ✓ VERIFIED | Unchanged; 02-09/02-10 both deployed/verified `--frontend-only` to archi-dev-box only; archy-x250-dev remained offline throughout and is honestly recorded as not yet receiving this phase's build |
**Score:** 6/8 truths verified (2 explicitly FAILED per the phase's own self-reported, git-committed measurement data — not inferred or code-read)
**Score:** 5/8 truths verified (3 explicitly FAILED: truths 2, 3, 6 — all downstream of the same confirmed, unfixed timing-regression finding)
### Required Artifacts
### Required Artifacts (gap-closure additions)
| Artifact | Expected | Status | Details |
|----------|----------|--------|---------|
| `neode-ui/e2e/perf/{surfaces,measure,surface-perf.spec}.ts` | Re-runnable perf harness | ✓ VERIFIED | Present, exports match must_haves, re-run twice (baseline + after) producing directly comparable artifacts |
| `.planning/phases/02-ui-performance/02-PERF-BASELINE.json` / `02-PERF-AFTER.json` | Pre/post measurements | ✓ VERIFIED | Both present, committed, 15/15 rows each |
| `.planning/phases/02-ui-performance/02-FINDINGS.md` | Cause-per-surface + before/after comparison | ✓ VERIFIED | All required sections present; Results/Outstanding sections added by 02-08 |
| `neode-ui/src/composables/useCachedResource.ts` | Stale-while-revalidate composable | ✓ VERIFIED | Exists, 5834 bytes, `onActivated` wiring confirmed |
| `neode-ui/src/views/dashboard/keepAliveRoutes.ts` | `shouldKeepAlive`, `KEEP_ALIVE_PATHS`, `KEEP_ALIVE_MAX` | ✓ VERIFIED | Present, documents both withholding reasons (D-02 already-fast, Settings unaudited-risk) |
| `neode-ui/src/components/RefreshIndicator.vue` | Background-refresh indicator | ✓ VERIFIED | Present, 1651 bytes |
| `neode-ui/src/views/dashboard/DashboardRouterView.vue` | KeepAlive host | ✓ VERIFIED | Present (per 02-02 files_modified, referenced by keepAliveRoutes.ts comments) |
| `neode-ui/src/stores/resources.ts` `clearAll()` / `auth.ts` `logout()` purge | Session-scoped cache clearing | ✓ VERIFIED (by SUMMARY test coverage; not independently re-run) | `resourcesClear.test.ts` referenced in 02-03 files_modified |
| `neode-ui/e2e/perf/keepalive-remount-probe.spec.ts` | Re-runnable, instrumented remount probe | ✓ VERIFIED | Present (530 lines), committed in `4d471759`; confirmed via `git diff --stat 3ee20430 -- neode-ui/e2e/perf/` that it is the ONLY change to that directory (the frozen 02-01 harness is untouched) |
| `neode-ui/src/views/dashboard/__tests__/keepAliveLifecycle.test.ts` (`02-09 gap closure` block) | 4 `vm.$.uid`-based regression tests | ✓ VERIFIED, RE-RUN THIS PASS | `npx vitest run` of this file: 16/16 tests pass, including all 4 new gap-closure tests (Test 1 "the gap", Test 2 "no collateral damage", Test 3 "registration is really the include list", Test 4 "the bound stays bound") |
| `.planning/phases/02-ui-performance/02-PERF-REMEASURE.json` | Third measurement, 5 runs/surface | ✓ VERIFIED | Present, committed (`db629f6f`); 15 rows, `runs: 5`, `baseUrl: http://archi-dev-box` per 02-10-SUMMARY |
| `.planning/phases/02-ui-performance/02-FINDINGS.md` `## Server KeepAlive Root Cause` + `## Re-measurement` sections | Named causes, evidence, verdicts | ✓ VERIFIED | Both sections present (lines 452-857), each verdict cites specific artifact fields, both committed before/alongside their respective source changes (or no-change decisions) |
| `keepAliveTabs.test.ts` | Must stay byte-for-byte unmodified (structural visual-contract pin) | ✓ VERIFIED | `git log --oneline -- neode-ui/src/views/dashboard/__tests__/keepAliveTabs.test.ts` shows no commits since 02-02; untouched by 02-09/02-10 |
### Key Link Verification
### Data-Flow / Behavioral Verification
| From | To | Via | Status | Details |
|------|-----|-----|--------|---------|
| `DashboardRouterView.vue` | `keepAliveRoutes.ts` | `shouldKeepAlive(route)` | ✓ WIRED | Confirmed via keepAliveRoutes.ts imports/exports and 02-02/02-04 SUMMARY test coverage |
| `useCachedResource.ts` | Vue `onActivated` | reactivation triggers `refreshIfStale` | ✓ WIRED | Confirmed present in `useCachedResource.ts` and exercised by `Server.vue`'s own `onActivated` (grepped directly, line 944) |
| `Server.vue` | `useCachedResource.ts` | 7 load groups as keyed cached resources | ✓ WIRED (data caching) / ✗ NOT DELIVERING instance survival | RPC count dropped 8->2 confirming the cache wiring works; but the component itself still fully remounts, so the "instance reused" half of PERF-02 is not delivered for this tab |
| `.planning/phases/02-ui-performance/02-FINDINGS.md` | `02-PERF-BASELINE.json` / `02-PERF-AFTER.json` | every cause/verdict cites a baseline or after field | ✓ WIRED | Confirmed by direct read of the Results table |
Ran the single most relevant regression-test file directly during this verification pass (not taken on SUMMARY's word):
```
npx vitest run src/views/dashboard/__tests__/keepAliveLifecycle.test.ts
→ 16 passed (16), including all 4 "02-09 gap closure" tests
```
Confirmed the harness freeze claim directly:
```
git diff --stat 3ee20430..HEAD -- neode-ui/e2e/perf/surfaces.ts neode-ui/e2e/perf/measure.ts neode-ui/e2e/perf/surface-perf.spec.ts
→ (empty — instrument genuinely frozen across both gap-closure plans)
```
Confirmed the CR-01/FIPS security-review fixes 02-REVIEW.md claims are actually landed in code (background check, not a phase must-have, but bears on overall code-quality confidence):
```
grep persist neode-ui/src/views/web5/Web5.vue → web5.lnd-info / web5.networking-profits both `persist: false` (T-02-01)
grep persist neode-ui/src/views/Server.vue → server.fips-summary `persist: false`
neode-ui/src/stores/resources.ts → SCHEMA_MARKER_KEY / purge-on-mismatch migration logic present (CR-01 follow-up)
```
All confirmed present in the actual source, not just claimed in the review doc.
### Requirements Coverage
| Requirement | Source Plan | Description | Status | Evidence |
|-------------|-------------|-------------|--------|----------|
| PERF-01 | 02-01, 02-08 | Slowest surfaces profiled, causes named, targeted fixes | ✓ SATISFIED | `02-FINDINGS.md` — comprehensive, gated before src changes, re-run after with honest before/after comparison |
| PERF-02 | 02-02, 02-04, 02-05, 02-06, 02-07 | Main-tab switches render immediately from cached state, background refresh, no blank/spinner | ⚠️ PARTIAL | True for Home/Apps/Marketplace/Cloud/Web5/Fleet/Mesh(cached, though tab itself unmeasured on real device)/Chat; **not delivered for Server.vue** (genuine remount + slower revisit); Web5/Fleet also show unresolved "split signal" timing regressions despite surviving instance |
| PERF-03 | 02-03, 02-08 | Secondary screens open without blocking reload, instant on repeat, verified on real hardware | ⚠️ PARTIAL | Per-item caching correctly implemented and no blocking reload for the four converted secondary screens; but AppDetails/OpenWrtGateway revisit ms regressed and Wallet/send-flow's anomaly was never fixed; real-hardware D-11 checkpoint did pass overall |
| Requirement | Status | Evidence |
|-------------|--------|----------|
| PERF-01 | ✓ SATISFIED | Unchanged — profiling-before-fix discipline fully evidenced and gap-closure-consistent |
| PERF-02 | ✗ NOT SATISFIED | REQUIREMENTS.md marks this `[x] Complete`, citing 02-10's "closed" verdict — but the verdict itself records 3 of the 5 confirmed regressions (Server, Web5, Fleet) as unfixed main-tab timing regressions. "Closed" in the project's own tracker means "has a verdict," not "resolved to meet the requirement's own wording" ("render immediately... no blank screens or long spinners") |
| PERF-03 | ✗ NOT SATISFIED | Same discrepancy — AppDetails and OpenWrtGateway confirmed regressed and unfixed; REQUIREMENTS.md's "Complete" marking describes the verdict process, not the outcome |
REQUIREMENTS.md marks all three `[x]` Complete — this verification finds PERF-01 fully supported, but PERF-02 and PERF-03 only partially supported by the project's own measured evidence.
**This verification does not accept "a verdict now exists" as equivalent to "the requirement is met."** A confirmed-real, unfixed, phase-2-caused regression is a requirement failure, not a closed requirement, regardless of how well it is documented.
### Anti-Patterns Found
None found in the reviewed source (`keepAliveRoutes.ts`, `Server.vue`, `useCachedResource.ts`) — no TODO/FIXME/XXX/placeholder markers, no stub returns. The self-reported gaps above come from the phase's own honest measurement artifacts, not from code smells.
None in the gap-closure files themselves (`keepalive-remount-probe.spec.ts`, `keepAliveLifecycle.test.ts` additions, `02-FINDINGS.md`) — no stubs, no TODO/FIXME/XXX, no hand-edited artifacts. The gap-closure work product is itself high quality; the gap is in the underlying performance outcome, not in how it was investigated or reported.
### Human Verification Required
### 1. Server.vue's actual on-device feel despite the remount
**Test:** On archi-dev-box, switch away from Server and back several times; watch specifically for a spinner or blank frame (not just "does it look fine overall").
**Expected:** No visible spinner/blank frame — Server's RPC count dropped from 8 to 2, so even a full remount may resolve fast enough to feel instant.
**Why human:** The D-11 checkpoint's "approved" covered general tab-cycling including Server, but the specific remount finding was written up by an automated pass (Task 2) that ran before the human walkthrough (Task 3); no record shows the reviewer's attention was drawn to this specific finding.
### 2. Timing-regression surfaces: real regression or environmental noise
**Test:** Re-run the 02-01/02-08 harness against archi-dev-box at the same time of day as the original baseline (10:30 local), on an idle node.
**Expected:** Either the regressions on Discover/Web5/AppDetails/OpenWrtGateway shrink or disappear (confirming environmental noise), or they persist (confirming a real regression needing a fix).
**Why human:** Requires scheduling a controlled re-run; FINDINGS.md itself names this exact caveat but does not resolve it.
See frontmatter `human_verification` — two items: (1) a felt-experience check on Discover/AppDetails/OpenWrtGateway specifically (never covered by any checkpoint after the regression was confirmed), and (2) an explicit accountable stakeholder decision on whether to accept the five confirmed regressions as a scoped-out follow-up or require a fix-and-reverify pass before this phase can be considered done.
### Gaps Summary
Phase 2 delivered a substantial, well-tested KeepAlive + `useCachedResource` architecture, and the team's own verification discipline in this phase was unusually strong: a D-10 measure-before-fix gate that was actually honored (confirmed by git-log ordering), a checkpoint-caught margin/animation regression fixed and re-verified in 02-02, a Cloud first-click connection-pool-starvation regression found and fixed during the final D-11 checkpoint (root-caused via direct instrumentation, not guessed), and honest self-reporting of every regression and gap in `02-FINDINGS.md` rather than averaging them away or hiding them — the phase's own artifacts are unusually candid.
**What closed cleanly:** Gap 1 (Server.vue's reported KeepAlive remount) is genuinely resolved, and resolved well. 02-09 did not take the easy path of accepting 02-08's "confirmed twice" finding at face value — it built a third, more rigorously instrumented probe, found an authoritative contradicting signal (`document.elementFromPoint()` hit-testing across four independent device runs, zero readings the other direction), named the actual mechanism (a generic, shared CSS selector that cannot disambiguate the foreground tab from other still-cached tabs once more than one is resident — which is the normal, intended KeepAlive state), and pinned the corrected understanding with four `vm.$.uid`-based regression tests immune to the same ambiguity. I re-ran those tests directly in this pass rather than trusting the SUMMARY: 16/16 green. This is exactly the kind of skepticism-then-verification this verifier is supposed to model, and it was applied by the executing agent to its own team's prior finding.
That candor is exactly what surfaces the two gaps blocking a clean pass: (1) Server.vue, registered for instance caching since 02-04, is confirmed — via a corrected probe method reproduced twice specifically to rule out a fluke — to still fully remount on every tab revisit, a direct contradiction of 02-08's own must-have truth and of PERF-02's substance for that one tab; and (2) six of the roughly nine surfaces the findings doc named as slow (Discover, Server, Web5, AppDetails, OpenWrtGateway, Wallet/send-flow) show a regressed or unchanged revisit time in the after-measurement despite the architecture landing, a direct contradiction of another 02-08 must-have. Both are self-documented in `02-FINDINGS.md`'s own `## Outstanding` section as open, non-blocking follow-ups, and both are plausible candidates for a same-time-of-day/environmental-noise explanation the findings doc itself flags but does not resolve. The final D-11 human checkpoint did walk every main tab (including Server) and multiple secondary screens and returned "approved" after the one regression that was surfaced (Cloud) was fixed — but there is no record that the specific Server-remount finding or the specific per-surface timing regressions were called out to the reviewer as items requiring an explicit accept/reject decision, as opposed to being folded into a general "much better" impression. Given the phase's own must-have truths explicitly name these as required outcomes and no later roadmap phase claims ownership of closing them, this verification cannot silently pass them — they are reported as gaps with a clear override path (both are named in the frontmatter's `human_verification` section, and either could be resolved with a targeted fix or an explicit accepted-deviation override added to a re-verification pass).
**What did not close:** Gap 2 (timing regressions) went through the same rigorous process — a three-way dispersion comparison across 3 independent runs on 3 different days, git-log bisection to confirm phase-2 origin, explicit ruling-out of the environmental-noise theory with data (the regressions grew as disk pressure eased, the opposite of a noise signature) — and the answer it produced is that 5 of 6 named surfaces are genuinely, measurably, unambiguously worse than before this phase touched them, in some cases dramatically so (Web5 +135%, AppDetails +122%, OpenWrtGateway +120%, Fleet — bonus/out-of-scope — +697%). None of the five is fixed. The reason given is an operational one (a concurrent session's uncommitted work made a second deploy unsafe this session), not a judgment that the regression is acceptable — the plan's own text explicitly frames "fix it" as the intended action for exactly this situation ("Confirmed AND caused by a phase-2 change AND fixable small -> fix it"), and only fell back to "accepted deviation" because that branch became unavailable mid-session.
**The central judgment call this re-verification was asked to make:** does "the UI feels fast" hold when tab-switching is genuinely instant and user-confirmed on hardware, but five named surfaces measurably regressed on revisit? My answer is no, not yet, for two reasons grounded directly in the project's own evidence rather than my own intuition about UX: first, the harness's own field definition for `revisitMs` is "wall-clock ms from the click that starts navigation to the surface's contentSelector becoming visible" — this is a direct, literal measurement of the exact thing the phase goal describes ("renders promptly instead of stalling"), not a proxy or an internal metric a user wouldn't feel. A 2.7-second wait for AppDetails' content to become visible, or a 1.3-second wait for Web5, is squarely within what SC2/SC3's own language ("no blank screens or long spinners," "instant") was written to rule out. Second, these are not edge-case or rarely-visited surfaces — Server and Web5 are main tabs, exactly the class of surface PERF-02 exists to fix, and both are now slower than they were before the phase started at all (738→1239ms, 566→1329ms), which is the opposite outcome the phase set out to produce. The user's hands-on approval in 02-09's Task 3 checkpoint is real and valuable evidence, but it was scoped specifically to Server/Web5's remount-and-visual-contract question (spinner/blank-frame/margins/transitions) — it did not, and could not, cover Discover/AppDetails/OpenWrtGateway, and it predates 02-10's confirmation that the timing cost is real rather than noise. An "accepted deviation" written by the executing agent under a deploy-safety constraint is not the same thing as an accountable stakeholder deciding this trade-off is fine; that decision has not yet been made by anyone empowered to make it, so this verification cannot manufacture it on the project's behalf, and continues to report this as a gap rather than closing it as an override.
This is not a rejection of the team's work quality — the investigation discipline in both 02-09 and 02-10 (measure before fix, dispersion over medians, git-bisection to confirm origin, explicit noise-theory falsification) is unusually strong and exactly what should happen when a gap-closure pass finds bad news. But finding bad news rigorously does not convert it into good news, and the phase's own goal — "the UI feels fast" — is not yet true for Server, Web5, Discover, AppDetails, and OpenWrtGateway.
---