archy/.planning/STATE.md
archipelago f514ab515b docs(02-11): complete plan — leaked-poller fix, four-way verdicts, SUMMARY
Phase 02's last open item closed: web5/server/fleet fixed and proven
on archi-dev-box; app-details restored to at/near baseline;
discover's second cause (CSS entrance-animation replay on KeepAlive
reactivation) named and evidenced but not fixed, scoped as a
follow-up; openwrt-gateway not measurable this pass, prior numbers
flagged not retracted.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-31 09:37:54 -04:00

20 KiB
Raw Blame History

gsd_state_version: 1.0 milestone: v1.8.0 milestone_name: milestone current_phase: 02 current_phase_name: ui-performance status: verifying stopped_at: Completed 02-11-PLAN.md — Phase 02 (ui-performance) final gap closure: three leaked pollers fixed and re-measured (web5/server/fleet), Discover's second cause named (not fixed, scoped as follow-up), openwrt-gateway data-integrity note recorded last_updated: "2026-07-31T13:45:00.000Z" last_activity: 2026-07-31 last_activity_desc: 02-11 gap closure complete — leaked background pollers fixed, four-way re-measure verdicts written progress: total_phases: 9 completed_phases: 2 total_plans: 28 completed_plans: 18 percent: 23

Project State

Project Reference

See: .planning/PROJECT.md (updated 2026-07-29)

Core value: A third-party developer can publish an app via the signed/decentralized registry and a user can install it on their node — manifest-driven, rootless, secure, robust. Current focus: Phase 02 — ui-performance

Current Position

Phase: 02 — gap closure complete (02-11 was the last open item) Plan: 11 of 11 complete Status: 02-11 complete — three leaked background pollers fixed and re-measured; Discover's second cause named, not fixed (scoped follow-up); openwrt-gateway unmeasurable this pass (browser crash), prior numbers stand with a data-integrity note Last activity: 2026-07-31 — 02-11 gap closure complete

Progress: [███████░░░] 67%

Performance Metrics

Velocity:

  • Total plans completed: 0
  • Average duration: —
  • Total execution time: —

By Phase:

Phase Plans Total Avg/Plan
- - - -
Per-Plan Metrics:
Plan Duration Tasks Files
Phase 02 P01 100min 3 tasks 5 files
Phase 02 P03 45min 3 tasks 5 files
Phase 02 P02 105min 3 tasks 11 files
Phase 02 P04 150min 3 tasks 12 files
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
Phase 02 P09 130min 3 tasks 3 files
Phase 02 P10 55min 2 tasks 3 files
Phase 02 P11 ~150min 3 tasks 8 files

Accumulated Context

Roadmap Evolution

  • Phase 1 added (2026-07-29): Federation & Mesh Hardening — user-directed top priority (node removal/sync issues, mesh attachment parity incl. demo); prior phases shifted down
  • Phase 2 added (2026-07-29): UI Performance — slow tab switches and secondary screens; prior phases shifted down
  • FED-05 added to Phase 1 (2026-07-29): inter-node Lightning channel-opening UX (share node URI, pick trusted/federated nodes by hostname, request channels with public nodes); UI tested on :8100 dev preview against archi-dev before deploy
  • FED-06 added to Phase 1 (2026-07-29): on-brand paid-tick animation — screensaver ring + EQ segments (reuse ScreensaverRing.vue compact) replacing the success burst in SendBitcoinModal.vue
  • Phase 9 added (2026-07-30): BotFights Platform Upgrade — native nostr signer login, unified AI bot-setup prompt replacing docs page, shared public match endpoint on VPS2 (all nodes see all fighters), registry/manifest update. Independent of Phases 18.

Decisions

Decisions are logged in PROJECT.md (10 locked ADRs in the <decisions> block + milestone decisions table). Recent decisions affecting current work:

  • Milestone version = 1.8.0-alpha (decided 2026-07-08)
  • Phase-3 Quadlet default-flip is gated on the second-node gate reporting clean (do fresh, never stage uncommitted)
  • Workstream D (DHT distribution) deferred to v2 — design-only backlog
  • Canonical manifest schema = core/container/src/manifest.rs (code wins over spec doc)
  • [Phase ?]: Marketplace is the 02-02 tracer tab (worst-measured main tab, 2033ms revisit) matching the user's own 'often app store' complaint
  • [Phase ?]: ContainerAppDetails.vue confirmed fully unreachable dead code (no importer, no route) — no serial-RPC-waterfall target exists in the measured D-09 surface set
  • [Phase ?]: archi-dev-box UI password was unknown/undiscoverable from this environment — paused at a checkpoint:human-action rather than guessing or falling back to a mock baseline silently
  • [Phase ?]: Purged the resource cache on logout via clearAll() + a generation guard, so no in-flight fetch from an ending session can repopulate memory or sessionStorage (T-02-02)
  • [Phase ?]: AppDetails/MarketplaceAppDetails/OpenWrtGateway converted to per-item (or single-key) keyed useCachedResource; CloudFolder.vue's existing store-level cache left as-is (cloud.ts TTL gate is a follow-up, out of this plan's file scope)
  • [Phase ?]: Wallet/send flow (SendBitcoinModal.vue) reported as an unplanned-item gap — named by findings as owned by 02-03 but not in files_modified; its cost is pure client-side remount, not a caching problem
  • [Phase ?]: PERF-03 reverted to Pending in REQUIREMENTS.md after an initial mark-complete was premature — its own text requires real-node-hardware verification, which is 02-08's job (also declares PERF-03); 02-03 delivers the code-level portion only
  • [Phase ?]: 02-02: DashboardRouterView final shape uses statically-named per-route KeepAlive wrapper components (dashboardViewWrappers.ts) with :include name-matching, restoring pre-restructure view-wrapper DOM/animations byte-for-byte after a checkpoint-caught regression
  • [Phase ?]: 02-02: HARD RULE for rest of Phase 02 — perf work must be visually invisible; verify against the real dev preview before considering a checkpoint satisfied
  • [Phase ?]: 02-02: app-catalog persist:true ttl 300000ms; bitcoin.prune-status persist:true ttl 30000ms — both explicit per T-02-01, no default relied on
  • [Phase ?]: 02-02: PERF-02 reverted to Pending/In-Progress in REQUIREMENTS.md after an automated mark-complete run — PERF-02 also spans 02-04..02-07 (extending KeepAlive caching to every remaining main tab); this plan proves the architecture on the tracer tab only
  • [Phase ?]: 02-04: KEEP_ALIVE_PATHS widened to every audited main tab (10 paths) derived from TAB_ORDER + /dashboard/discover; /dashboard/settings deliberately withheld — its child sections (SystemDangerZone reboot poll, several onMounted-only fetches) were never audited by this plan
  • [Phase ?]: 02-04: onActivated is a documented no-op outside a KeepAlive boundary — every arm function now runs from both onMounted and onActivated (fresh-mount guards on Home/Web5/Mesh/Server avoid doubling first-load RPC cost); caught by CloudPeersRefresh.test.ts
  • [Phase ?]: 02-04: useCachedResource.ts's onActivated no longer eagerly force-loads a never-fetched immediate:false resource, so tab-gated lazy data (Cloud.vue Paid Files/My Files) isn't force-loaded merely by its view entering the KeepAlive cache
  • [Phase ?]: 02-04: AIUI blank-screen-and-loading symptom reported at Task 3 checkpoint diagnosed as pre-existing (local mock-backend dev mode sets VITE_AIUI_URL=http://localhost:5173 unconditionally with no AIUI repo checked out) — not a regression, left for 02-07 (Chat/AIUI) to address
  • [Phase ?]: 02-05: mesh.refreshAll()/transport.fetchStatus() stay uncached at the store level (other callers need guaranteed-fresh reads); the useCachedResource wrapper around each lives in Mesh.vue instead, since Pinia's defineStore(id,setup) runs in a bare effectScope where onActivated() silently no-ops
  • [Phase ?]: 02-05: FLAGGED - RESEARCH.md's premise that Mesh.vue owns a D3 force simulation is incorrect for this codebase (verified via grep); only NetworkMap.vue/Federation.vue has one. Task 2's D3 truths are vacuously satisfied; only the real Leaflet map lifecycle (MeshMap.vue, added to scope) was implemented
  • [Phase ?]: 02-05: per-group TTL/persist table - mesh.refresh-all/federation-nodes/self-onion/self-did/contacts all persist:false (identity payload); transport-status persists (aggregate, non-identity); reachability groups get 10s TTL, identity groups 300s
  • [Phase ?]: 02-06: RESEARCH A3 settled — none of Server's seven load-group loaders consumes another's result; concurrent fan-out is correct as-is
  • [Phase ?]: 02-06: Five of Server's seven groups were already on useCachedResource from a pre-phase legacy commit (ea254f63) with only composable defaults (30s TTL, persist:true) — this plan's work was explicit TTL/persist/dedup, not initial conversion; only loadDiskStatus was a genuinely uncached plain fetch
  • [Phase ?]: 02-06: Home's wallet composite does NOT share a cache key with Web5.vue's web5.lnd-info — sharing would either corrupt Web5's typed entry.data or fail to close the sessionStorage gap since Web5.vue's own hook (out of scope) defaults persist:true
  • [Phase ?]: 02-06: homeStatus.refresh() wrapped by useCachedResource at Home.vue (the view), not inside the homeStatus Pinia store — defineStore(id,setup) runs in a bare effectScope where onActivated() silently no-ops, same finding as 02-05's Mesh.vue
  • [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
  • [Phase ?]: 02-09: /dashboard/server's (and Web5's) 'genuinely remounts' reading was a proven probe-measurement artifact (generic .view-container selector can't disambiguate the foreground tab from other still-connected cached tabs) — confirmed via document.elementFromPoint() hit-test contradicting the naive verdict across device runs; no source change needed, pinned with vm.$.uid-based regression tests instead
  • [Phase ?]: 02-09: committed neode-ui/e2e/perf/keepalive-remount-probe.spec.ts as a re-runnable, instrumented probe covering every KEEP_ALIVE_PATHS tab, replacing the ad-hoc 02-08 probe so this class of false positive cannot recur
  • [Phase ?]: [Phase 2, gap closure 02-10]: Wallet/send-flow's timing regression cleared as environmental noise (re-measure at/below baseline); Discover/Server/Web5/AppDetails/OpenWrtGateway confirmed as real, phase-2-caused client-side render/reactivation regressions via 3-run dispersion + git bisection, recorded as accepted deviations (not fixed — deploy blocked mid-session by a shared-tree hazard with concurrent security-follow-up and BotFights sessions)
  • [Phase 2, gap closure 02-11]: Real cause of the six regressions was NOT compute-bound render cost (CPU profile: 86-99% idle/program, <10% JS self-time everywhere) — it was three background pollers (useFleetData.ts 60s, FipsNetworkCard.vue 15s, Web5Monitoring.vue 30s) armed in onMounted and never disarmed once their owning views joined KEEP_ALIVE_PATHS in 02-04, invisible to that audit because it grepped the top-level view files, not the child composables they delegate to. Gated to onActivated/onDeactivated, mirroring 02-04's own established pattern. Fixed: web5 275ms (was 566ms baseline/1329ms regressed), server 574ms (was 738/1239), fleet 790ms (was 330/2631)
  • [Phase 2, gap closure 02-11]: Discover (1389ms, worst remaining) has a SECOND, distinct cause: card-stagger/showStagger entrance-animation classes are baked into the DOM at first mount and never programmatically removed, so every KeepAlive detach/reattach cycle restarts the CSS animation on reactivation — replaying the full entrance cascade on every revisit. Confirmed via a diagnostic (DOM card count doubling transiently on every revisit) and an extended animation-event log. NOT fixed — blast radius spans 5+ files outside 02-11's scope (Apps.vue, Marketplace.vue, Home.vue, several Web5 sub-cards), needs its own real-device verification budget; recommended as a dedicated follow-up
  • [Phase 2, gap closure 02-11]: openwrt-gateway unmeasurable in the final re-measure (Chromium "Target crashed" cascading from an unrelated surface, cloud-folder, earlier in the same harness run) — recorded as not-measurable, not written in as data. Separately confirmed the prior baseline/after/remeasure numbers were measuring a real, substantive disconnected-state UI (OpenWrtGateway.vue's h1 is unconditional; a "No router configured" RPC error deterministically renders a real Connect-to-Router form, not a blank/error page) — the six-surface regression count is not retracted, but the numbers reflect one specific code branch (no OpenWrt device has ever been connected to archi-dev-box)

Pending Todos

  • [blocker/ui] Keep FIPS/Tor pills on cloud files and show them on mobile (.planning/todos/pending/2026-07-30-keep-fips-tor-pills-on-cloud-files-and-show-them-on-mobile.md)
  • [blocker/security] Fedimint gateway must not install with a pre-set password — tracked as FED-07 / Phase 1 gap plan (.planning/todos/pending/2026-07-30-fedimint-gateway-must-not-install-with-preset-password.md)
  • [blocker/ui] Connected-nodes list must scroll at row-matched height, not grow to fit (.planning/todos/pending/2026-07-30-connected-nodes-list-must-scroll-at-row-matched-height.md)
  • [blocker/ui] Onboarding tickbox hidden below fold on short screens — make it beautifully obvious (.planning/todos/pending/2026-07-30-onboarding-tickbox-hidden-below-fold-on-short-screens.md)
  • [major/ui] Paid Files pictures open in browser tab, not the app lightbox — UIFIX-04 (.planning/todos/pending/2026-07-30-peer-files-pictures-open-in-tab-not-lightbox.md)
  • [major/ui] PiP should close the lightbox with a fluid animation — UIFIX-05 (.planning/todos/pending/2026-07-30-pip-should-close-lightbox-with-fluid-animation.md)
  • [major/ui] Missing loader states on slow opens — UIFIX-06 (.planning/todos/pending/2026-07-30-missing-loader-states-on-slow-opens.md)

Blockers/Concerns

  • [Phase 1] Federation tombstone fix touches trust code — fix carefully, re-verify with tests/multinode/smoke.sh, don't patch blind
  • [Phase 3] Multinode gate on archy-x250-beta was launched 2026-07-01 (log on-node); verify outcome before re-running
  • [Phase 5] Fleet registry flip awaits explicit user authorization + timing call
  • [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, RESOLVED by 02-09] Server.vue does not survive a tab round-trip despite KEEP_ALIVE_PATHS registration — retracted: proven a probe-measurement artifact (shared generic .view-container selector couldn't disambiguate the foreground tab from other cached tabs), not a real defect. Server.vue's (and Web5.vue's) instance genuinely survives; pinned with vm.$.uid-based regression tests immune to the same ambiguity. Checkpoint approved on real hardware.
  • [Phase 2, RESOLVED by 02-11] Timing regressions on Discover/Web5/Fleet/AppDetails/OpenWrtGateway — root cause found (three leaked background pollers, not compute-bound render cost) and fixed for web5/server/fleet, each proven with a real before/after number on archi-dev-box. AppDetails restored to at/near its own pre-phase-2 baseline (pre-existing per-mount cost, not a new defect). OpenWrtGateway not measurable this pass (browser crash); prior numbers stand with a data-integrity note (measuring a real disconnected-device UI, not an empty page).
  • [Phase 2, follow-up needed] Discover (1389ms, worst remaining named surface) has a second, evidenced, phase-2-caused defect: KeepAlive'd entrance-stagger animations (card-stagger/showStagger) never get their class removed from the DOM after first play, so every reactivation replays the full CSS animation cascade. Fix requires touching 5+ files outside 02-11's scope (Apps.vue, Marketplace.vue, Home.vue, Web5Wallet.vue/Web5Identities.vue/Web5NodeVisibility.vue/Web5NostrRelays.vue) with its own real-device visual-regression verification budget (the same class of risk 02-02's original KeepAlive rollout hit on its first checkpoint attempt) — needs a dedicated follow-up plan, not squeezed into a gap-closure pass.

Quick Tasks Completed

# Description Date Commit Directory
260729-fw7 improve mesh message hop graphic/animation: balanced desktop sizing, vertical mobile layout, archipelago branding 2026-07-29 ac09fc5d 260729-fw7-improve-mesh-message-hop-graphic-animati
260729-gjd demo: indee.tx1138.com in app iframe (:2101 whole-origin proxy), auto nostr signer sign-in, IndeeHub pre-installed on fresh session 2026-07-29 d00ca624 260729-gjd-demo-make-indee-tx1138-com-work-in-the-a
260729-hj1 peer-files media batch: Wavlake paid tracks + purchases + dedupe + real photos (demo); lightbox/player open routing + free-image lightbox fix (both builds) 2026-07-29 f52c5407 260729-hj1-peer-files-media-batch-wavlake-paid-trac
260729-je5 connected-nodes list fills card height (constant footer gap); companion app skips demo intro 2026-07-29 d54517cf 260729-je5-ui-fixes-connected-nodes-scrollable-list

Deferred Items

Category Item Status Deferred At
Distribution DIST-01 DHT/iroh backbone (workstream D) v2 2026-07-29
Fleet FLEET-01 Bitcoin multi-version fleet OTA (user-gated) v2 2026-07-29
Fleet FLEET-02 per-app deep health assertions (~34 apps) v2 2026-07-29
Fleet FLEET-03 LUKS2 data-partition encryption v2 2026-07-29

Session Continuity

Last session: 2026-07-31T13:45:00.000Z Stopped at: Completed 02-11-PLAN.md — Phase 02 (ui-performance) final gap closure complete Resume file: None