Archipelago — open-source initial import
This commit is contained in:
@@ -0,0 +1,368 @@
|
||||
---
|
||||
phase: 02-ui-performance
|
||||
plan: 01
|
||||
type: execute
|
||||
wave: 1
|
||||
depends_on: []
|
||||
files_modified:
|
||||
- neode-ui/e2e/perf/surfaces.ts
|
||||
- neode-ui/e2e/perf/measure.ts
|
||||
- neode-ui/e2e/perf/surface-perf.spec.ts
|
||||
- .planning/phases/02-ui-performance/02-PERF-BASELINE.json
|
||||
- .planning/phases/02-ui-performance/02-FINDINGS.md
|
||||
autonomous: true
|
||||
requirements: [PERF-01]
|
||||
|
||||
must_haves:
|
||||
truths:
|
||||
- "Every surface in the D-09 starting set (Apps, Marketplace/Discover app store, Mesh, Wallet/send flows, Cloud/Files, Server, Network, Web5, plus AppDetails) has a recorded first-visit and revisit measurement in 02-PERF-BASELINE.json"
|
||||
- "For each measured surface the findings doc names exactly one primary cause drawn from the closed set: remount storm, serial RPC waterfall, uncached fetch, or already-fast"
|
||||
- "Each named cause is backed by a number in 02-PERF-BASELINE.json (revisit ms, revisit RPC count, or remount-probe result) — not by code reading alone"
|
||||
- "02-FINDINGS.md is committed to git before any production source file under neode-ui/src is modified by this phase (D-10)"
|
||||
- "The harness re-runs on demand and produces a comparable JSON artifact, so the same measurements can be taken again after the fixes land"
|
||||
- "A surface that could not be measured is recorded in the findings doc as unmeasured with the reason, and is never recorded as already-fast"
|
||||
- statement: "Running the harness twice against an unchanged build yields the same primary-cause classification for every surface"
|
||||
verification: backstop
|
||||
prohibitions:
|
||||
- "MUST NOT present inferred, code-read, or cherry-picked numbers as measured profiling results, and MUST NOT omit a D-09 surface from the findings doc because it was hard to measure — an unmeasured surface is recorded as unmeasured, never as already-fast"
|
||||
- "MUST NOT ship performance instrumentation that transmits, logs, or persists node or user activity off-device — profiling stays local to the developer's browser and harness run"
|
||||
- "MUST NOT commit node-identifying or account-identifying material (onion addresses, DIDs, pubkeys, wallet balances, file names, peer hostnames) into the profiling artifacts"
|
||||
artifacts:
|
||||
- path: "neode-ui/e2e/perf/surfaces.ts"
|
||||
provides: "SURFACES table — one row per D-09 surface with route path, content selector and view-root selector"
|
||||
exports: ["SURFACES", "type Surface"]
|
||||
- path: "neode-ui/e2e/perf/measure.ts"
|
||||
provides: "measureSurface() — first-visit vs revisit timing, RPC request trace, remount probe"
|
||||
exports: ["measureSurface", "type SurfaceMeasurement", "type RpcCall"]
|
||||
- path: "neode-ui/e2e/perf/surface-perf.spec.ts"
|
||||
provides: "Playwright spec that walks every SURFACES row and writes the JSON artifact"
|
||||
- path: ".planning/phases/02-ui-performance/02-PERF-BASELINE.json"
|
||||
provides: "Recorded pre-fix measurements for every D-09 surface"
|
||||
- path: ".planning/phases/02-ui-performance/02-FINDINGS.md"
|
||||
provides: "D-10 deliverable — surface, measured cause, intended fix, owning plan"
|
||||
key_links:
|
||||
- from: "neode-ui/e2e/perf/surface-perf.spec.ts"
|
||||
to: "neode-ui/e2e/perf/measure.ts"
|
||||
via: "imports measureSurface and calls it once per SURFACES row"
|
||||
pattern: "measureSurface"
|
||||
- from: "neode-ui/e2e/perf/measure.ts"
|
||||
to: "browser network layer"
|
||||
via: "page.on('request') / page.on('response') captures RPC POSTs so revisit RPC count is observed, not assumed"
|
||||
pattern: "page\\.on\\(['\"]request"
|
||||
- from: ".planning/phases/02-ui-performance/02-FINDINGS.md"
|
||||
to: ".planning/phases/02-ui-performance/02-PERF-BASELINE.json"
|
||||
via: "every named cause cites the baseline row it came from"
|
||||
pattern: "02-PERF-BASELINE"
|
||||
---
|
||||
|
||||
<objective>
|
||||
Measure the D-09 surfaces on real node hardware, name each one's primary cause from
|
||||
observed numbers, and commit the findings doc that gates every fix in this phase.
|
||||
|
||||
Purpose: PERF-01 and D-10 require that fixes are targeted, not guessed. Nothing under
|
||||
`neode-ui/src/` changes in this plan — the harness lives entirely in `neode-ui/e2e/perf/`
|
||||
so the "measure before you fix" ordering is structurally guaranteed rather than merely
|
||||
promised.
|
||||
|
||||
Output: a re-runnable Playwright perf harness, a committed baseline JSON, and
|
||||
`02-FINDINGS.md` mapping each surface to a measured cause and the plan that fixes it.
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@$HOME/.claude/gsd-core/workflows/execute-plan.md
|
||||
@$HOME/.claude/gsd-core/templates/summary.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
@.planning/PROJECT.md
|
||||
@.planning/ROADMAP.md
|
||||
@.planning/STATE.md
|
||||
@.planning/phases/02-ui-performance/02-CONTEXT.md
|
||||
@.planning/phases/02-ui-performance/02-RESEARCH.md
|
||||
@.planning/phases/02-ui-performance/02-PATTERNS.md
|
||||
@CLAUDE.md
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Build the re-runnable surface perf harness</name>
|
||||
<files>neode-ui/e2e/perf/surfaces.ts, neode-ui/e2e/perf/measure.ts, neode-ui/e2e/perf/surface-perf.spec.ts</files>
|
||||
<read_first>
|
||||
- neode-ui/playwright.config.ts — testDir is `./e2e`, baseURL comes from `ARCHY_BASE_URL` (default `http://192.168.1.228`), single `chromium` project, 60s timeout
|
||||
- neode-ui/e2e/app-launch.spec.ts — the existing login/navigation flow to reuse verbatim; do not invent a second auth path
|
||||
- neode-ui/e2e/intro-experience.spec.ts — how the existing specs get past the intro/splash gating so a measurement does not accidentally time the intro animation
|
||||
- neode-ui/src/router/index.ts — the authoritative route table; every `SURFACES` path must exist here
|
||||
- neode-ui/src/views/dashboard/useRouteTransitions.ts — `TAB_ORDER` is the canonical main-tab path list
|
||||
- neode-ui/src/api/rpc-client.ts — the RPC transport, so the request filter matches the real endpoint shape rather than a guess
|
||||
</read_first>
|
||||
<action>
|
||||
Create `neode-ui/e2e/perf/surfaces.ts` exporting `type Surface` and a `SURFACES`
|
||||
array. One row per D-09 surface, each row carrying: `id`, `label`, `path`,
|
||||
`kind` (`main-tab` or `secondary`), `contentSelector` (a selector that is only
|
||||
present once real content has painted, not a skeleton or spinner), and
|
||||
`rootSelector` (the stable outermost element of the view, used by the remount probe).
|
||||
Rows required by D-09, using the real route paths from `router/index.ts`:
|
||||
`/dashboard` (home/wallet figures), `/dashboard/apps`, `/dashboard/marketplace`,
|
||||
`/dashboard/discover`, `/dashboard/cloud`, `/dashboard/mesh`, `/dashboard/server`,
|
||||
`/dashboard/web5`, `/dashboard/fleet`, `/dashboard/chat`, plus secondary rows
|
||||
`/dashboard/apps/:id` (AppDetails), `/dashboard/marketplace/:id`
|
||||
(MarketplaceAppDetails), `/dashboard/cloud/:folderId` (CloudFolder) and
|
||||
`/dashboard/server/openwrt` (OpenWrtGateway). Derive each `contentSelector` and
|
||||
`rootSelector` by reading the corresponding view file; prefer an existing stable
|
||||
class or a `data-` attribute already present over adding markup to `src/`.
|
||||
|
||||
D-09 also names "Wallet / send flows". RESEARCH.md could not locate a `Wallet.vue`.
|
||||
Locate the real wallet surface first (grep for `SendBitcoinModal`, `loadWeb5Status`,
|
||||
and wallet balance rendering under `neode-ui/src/views` and
|
||||
`neode-ui/src/components`), then add a row for wherever wallet figures and the send
|
||||
entry point actually live. If the wallet surface turns out to be a modal rather than
|
||||
a route, add a row with a `trigger` field naming the selector that opens it, and
|
||||
measure open-to-content instead of navigate-to-content.
|
||||
|
||||
Create `neode-ui/e2e/perf/measure.ts` exporting `measureSurface(page, surface,
|
||||
opts)` returning a `SurfaceMeasurement`. It must record, per surface:
|
||||
`firstVisitMs` (navigate from the dashboard home to the surface, wait for
|
||||
`contentSelector`), `revisitMs` (navigate away to a fixed neutral tab, then back,
|
||||
wait for `contentSelector`), `firstVisitRpcCount` and `revisitRpcCount` (POSTs
|
||||
captured via `page.on('request')`, filtered to the RPC endpoint the rpc-client uses),
|
||||
`revisitRpcCalls` (an ordered array of `{ method, startedAtMs, durationMs }` so
|
||||
overlapping vs. sequential call timing is visible in the artifact), `remounted`
|
||||
(see below), and `error` (a string when the surface could not be measured, with
|
||||
the other numeric fields left null). Take `runs` samples per surface (default 3)
|
||||
and record every sample plus the median — never only the best one.
|
||||
|
||||
Implement the remount probe without touching `src/`: on the first visit, in the
|
||||
page context, stamp the element matched by `rootSelector` with a unique value on a
|
||||
dataset key (for example `perfProbe`); after the away-and-back navigation, read the
|
||||
same key back. A surviving value means the component instance was reused; a missing
|
||||
value means the view remounted. Record the raw before/after values in the
|
||||
measurement so the conclusion is auditable.
|
||||
|
||||
Derive the serial-vs-parallel signal from `revisitRpcCalls`: expose a computed
|
||||
`maxConcurrentRpc` and `rpcWallClockMs` on the measurement so a waterfall (calls
|
||||
starting one after another, `maxConcurrentRpc` of 1) is distinguishable from an
|
||||
already-parallel fan-out without re-reading the code.
|
||||
|
||||
Create `neode-ui/e2e/perf/surface-perf.spec.ts`: a single Playwright test that logs
|
||||
in using the flow from `app-launch.spec.ts`, iterates `SURFACES`, calls
|
||||
`measureSurface` for each, and writes the full result array plus a run header
|
||||
(`baseUrl`, `takenAt`, `commit` from `git rev-parse --short HEAD`, `runs`) to the
|
||||
path given by the `ARCHY_PERF_OUT` environment variable, defaulting to
|
||||
`e2e/test-results/surface-perf.json`. A surface that throws is caught, recorded
|
||||
with its `error` string, and does not abort the remaining surfaces.
|
||||
|
||||
Redaction is part of the harness, not a later cleanup step: the measurement must
|
||||
record RPC method names and timings only. Do not capture request bodies, response
|
||||
bodies, page text, or screenshots into the JSON artifact.
|
||||
</action>
|
||||
<verify>
|
||||
<automated>cd neode-ui && npx tsc --noEmit -p tsconfig.json 2>&1 | grep -v 'e2e/test-results' ; npx playwright test e2e/perf/surface-perf.spec.ts --project=chromium --reporter=line</automated>
|
||||
</verify>
|
||||
<acceptance_criteria>
|
||||
- `neode-ui/e2e/perf/surfaces.ts` exports `SURFACES` and every entry's `path` appears in `neode-ui/src/router/index.ts`
|
||||
- `SURFACES` contains at least one row for each of: apps, marketplace, discover, cloud, mesh, server, web5, chat, home, fleet, and the located wallet surface
|
||||
- `neode-ui/e2e/perf/measure.ts` exports `measureSurface` and the file contains `page.on('request'`
|
||||
- `SurfaceMeasurement` carries all of `firstVisitMs`, `revisitMs`, `firstVisitRpcCount`, `revisitRpcCount`, `revisitRpcCalls`, `maxConcurrentRpc`, `remounted`, `samples`, `error`
|
||||
- `npx playwright test e2e/perf/surface-perf.spec.ts --project=chromium` exits 0 and writes a JSON file whose top-level array length equals `SURFACES.length`
|
||||
- The written JSON contains no request or response body text: `node -e "const r=require('./e2e/test-results/surface-perf.json');process.exit(JSON.stringify(r).match(/onion|did:|xpub|npub/i)?1:0)"` exits 0
|
||||
- `npx tsc --noEmit` reports no errors originating in `e2e/perf/`
|
||||
</acceptance_criteria>
|
||||
<done>The harness runs end to end against a reachable Archipelago node and emits a complete, body-free measurement artifact for every D-09 surface.</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Record the on-device baseline from archi-dev-box</name>
|
||||
<precondition>archi-dev-box resolves and its web UI answers over HTTP from this machine (`getent hosts archi-dev-box` returns at least one address and the base URL returns a 200/302 for `/`)</precondition>
|
||||
<files>.planning/phases/02-ui-performance/02-PERF-BASELINE.json</files>
|
||||
<read_first>
|
||||
- neode-ui/e2e/perf/surface-perf.spec.ts — the harness written in Task 1, for its env-var contract
|
||||
- neode-ui/playwright.config.ts — `ARCHY_BASE_URL` is the target override
|
||||
- scripts/dev-start.sh — how the :8100 dev preview is started, in case the node's own UI is not directly reachable and the preview must proxy to it
|
||||
- .planning/phases/02-ui-performance/02-CONTEXT.md — D-11 names archi-dev-box as the verification target and states the pass bar
|
||||
</read_first>
|
||||
<action>
|
||||
Run the Task 1 harness against archi-dev-box with `ARCHY_BASE_URL` pointed at that
|
||||
node and `ARCHY_PERF_OUT` set to
|
||||
`../.planning/phases/02-ui-performance/02-PERF-BASELINE.json`, with `runs` at 3.
|
||||
archi-dev-box resolves to IPv6 addresses in this environment; if the bare hostname
|
||||
does not connect, try the reachable address form and record the exact base URL used
|
||||
in the artifact's run header.
|
||||
|
||||
If the node's UI cannot be driven directly, fall back to the :8100 dev preview
|
||||
pointed at archi-dev per the phase's existing dev discipline, and record in the run
|
||||
header that the measurement was taken through the preview rather than against the
|
||||
node's own served bundle. Do not silently substitute the local mock backend — a
|
||||
mock-backend run is not an on-device baseline and must be labelled as such in the
|
||||
header if it is the only run that succeeds.
|
||||
|
||||
Add a `notes` field to the run header recording: the target actually used, the
|
||||
browser build, whether the node was otherwise idle, and any surface that had to be
|
||||
skipped and why. Commit the artifact.
|
||||
|
||||
Do not edit any file under `neode-ui/src/` in this task. If a surface cannot be
|
||||
measured because its `contentSelector` never appears, fix the selector in
|
||||
`neode-ui/e2e/perf/surfaces.ts` and re-run rather than dropping the surface.
|
||||
</action>
|
||||
<verify>
|
||||
<automated>node -e "const r=require('/home/archipelago/Projects/archy/.planning/phases/02-ui-performance/02-PERF-BASELINE.json'); const rows=r.results??r; if(!Array.isArray(rows)||rows.length===0)process.exit(1); const bad=rows.filter(x=>x.error==null&&(x.revisitMs==null||x.revisitRpcCount==null)); if(bad.length){console.error('incomplete rows',bad.map(b=>b.id));process.exit(1)} console.log('rows',rows.length)"</automated>
|
||||
</verify>
|
||||
<acceptance_criteria>
|
||||
- `.planning/phases/02-ui-performance/02-PERF-BASELINE.json` exists and parses as JSON
|
||||
- Its run header records `baseUrl`, `takenAt`, `commit`, `runs` and a `notes` string naming the actual target
|
||||
- Every `SURFACES` row appears in the results, each with either numeric measurements or a non-empty `error` string
|
||||
- No file under `neode-ui/src/` is modified by this task: `git diff --name-only HEAD -- neode-ui/src | wc -l` prints 0
|
||||
- The artifact is committed (`git log -1 --name-only` lists `02-PERF-BASELINE.json`)
|
||||
</acceptance_criteria>
|
||||
<done>A committed on-device baseline exists covering every D-09 surface, with the measurement target explicitly recorded.</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 3: Write and commit the D-10 findings doc</name>
|
||||
<files>.planning/phases/02-ui-performance/02-FINDINGS.md</files>
|
||||
<read_first>
|
||||
- .planning/phases/02-ui-performance/02-PERF-BASELINE.json — the numbers every claim must cite
|
||||
- .planning/phases/02-ui-performance/02-RESEARCH.md — the "Concrete Findings Per Surface" table is a hypothesis set to confirm or overturn, not a substitute for the measurement
|
||||
- .planning/phases/02-ui-performance/02-CONTEXT.md — D-02 (targeted not blanket), D-10 (doc before fixes), D-12/D-13 (fix scope)
|
||||
- .planning/phases/02-ui-performance/02-PATTERNS.md — the per-view conversion checklist the intended fixes should align with
|
||||
</read_first>
|
||||
<action>
|
||||
Write `.planning/phases/02-ui-performance/02-FINDINGS.md` with these sections:
|
||||
|
||||
1. `## Method` — the target used, the harness path, the run command with its env
|
||||
vars, the sample count, and what each recorded field means. State plainly which
|
||||
surfaces were measured on archi-dev-box and which (if any) were not.
|
||||
2. `## Per-Surface Findings` — a table with columns: Surface, First visit (ms,
|
||||
median), Revisit (ms, median), Revisit RPC count, Max concurrent RPC, Remounted,
|
||||
Primary cause, Intended fix, Owning plan. `Primary cause` takes exactly one value
|
||||
from `remount storm`, `serial RPC waterfall`, `uncached fetch`, `already fast`,
|
||||
or `unmeasured`. Every non-`unmeasured` row cites the baseline field that
|
||||
justifies the cause (a remount storm needs `remounted: true`; an uncached fetch
|
||||
needs a non-zero `revisitRpcCount`; a waterfall needs `maxConcurrentRpc` of 1 with
|
||||
two or more sequential calls).
|
||||
3. `## Ranked Fix Order` — the surfaces ordered worst-revisit-first. This ranking
|
||||
selects the tracer tab for plan 02-02.
|
||||
4. `## Surfaces Left Alone (D-02)` — every surface classified `already fast`, with
|
||||
its numbers, so the decision not to convert it is auditable.
|
||||
5. `## Corrections to Prior Research` — record, with evidence, any place the
|
||||
measurement overturns `02-RESEARCH.md`. At minimum confirm or refute this
|
||||
planner's finding that `neode-ui/src/views/ContainerAppDetails.vue` has no
|
||||
importer and no route entry (run `grep -rn "ContainerAppDetails" neode-ui/src` and
|
||||
paste the result) — RESEARCH.md names it as the confirmed serial-waterfall fix
|
||||
target, and if it is unreachable then no plan should spend effort on it and the
|
||||
real waterfalls must come from the measured `revisitRpcCalls` instead.
|
||||
6. `## Owning Plans` — map each surface to the plan number that fixes it, using the
|
||||
plan set for this phase (02-02 tracer/app store, 02-03 secondary screens, 02-04
|
||||
keep-alive lifecycle, 02-05 Mesh, 02-06 Server and Home, 02-07 Chat/AIUI).
|
||||
|
||||
Redact before committing: replace any onion address, DID, pubkey, hostname other
|
||||
than `archi-dev-box`, wallet figure, or file name that appears in a method name or
|
||||
note with a short placeholder. Method names and timings stay.
|
||||
|
||||
Commit this doc as its own commit, and make that commit the last one in this plan —
|
||||
it is the gate the rest of the phase depends on.
|
||||
</action>
|
||||
<verify>
|
||||
<automated>test -f /home/archipelago/Projects/archy/.planning/phases/02-ui-performance/02-FINDINGS.md && for s in '## Method' '## Per-Surface Findings' '## Ranked Fix Order' '## Surfaces Left Alone' '## Corrections to Prior Research' '## Owning Plans'; do grep -qF "$s" /home/archipelago/Projects/archy/.planning/phases/02-ui-performance/02-FINDINGS.md || { echo "missing: $s"; exit 1; }; done; echo OK</automated>
|
||||
</verify>
|
||||
<acceptance_criteria>
|
||||
- `02-FINDINGS.md` contains all six required headings
|
||||
- Every surface present in `02-PERF-BASELINE.json` appears as a row in the Per-Surface Findings table
|
||||
- Every row's Primary cause is one of the five allowed values
|
||||
- The doc references `02-PERF-BASELINE.json` at least once
|
||||
- `## Corrections to Prior Research` contains the literal output of the `ContainerAppDetails` grep
|
||||
- `git log --oneline -1 -- .planning/phases/02-ui-performance/02-FINDINGS.md` returns a commit
|
||||
- `git diff --name-only HEAD~3..HEAD -- neode-ui/src | wc -l` prints 0 — no production source changed in this plan
|
||||
</acceptance_criteria>
|
||||
<done>The findings doc is committed, every claim in it traces to a measured number, and the fix order for the rest of the phase is fixed in writing.</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<threat_model>
|
||||
## Trust Boundaries
|
||||
|
||||
| Boundary | Description |
|
||||
|----------|-------------|
|
||||
| archi-dev-box node → developer workstation | Real node data (RPC method names, timings, and anything else the harness might capture) crosses onto the workstation and into a git-tracked artifact |
|
||||
| git-tracked planning artifacts → repository history | Anything written into `02-PERF-BASELINE.json` / `02-FINDINGS.md` is permanent and pushed |
|
||||
|
||||
## STRIDE Threat Register
|
||||
|
||||
| Threat ID | Category | Component | Severity | Disposition | Mitigation Plan |
|
||||
|-----------|----------|-----------|----------|-------------|-----------------|
|
||||
| T-02-06 | Information Disclosure | `e2e/perf/measure.ts` artifact writer | medium | mitigate | Harness records RPC method names and timings only — no request bodies, response bodies, page text, or screenshots (Task 1); Task 3 adds a redaction pass before commit |
|
||||
| T-02-07 | Information Disclosure | `02-FINDINGS.md` committed to a pushed repo | medium | mitigate | Explicit redaction step in Task 3 for onion addresses, DIDs, pubkeys, wallet figures, peer hostnames and file names |
|
||||
| T-02-08 | Spoofing | Playwright login flow reusing dev credentials | low | accept | The harness reuses the existing `e2e/app-launch.spec.ts` auth flow against a developer-owned dev node; no new credential surface is introduced and none are written to the artifact |
|
||||
| T-02-SC | Tampering | npm/pip/cargo installs | high | mitigate | No package-manager installs are in scope: RESEARCH.md's Package Legitimacy Audit records zero new packages, and every primitive used is Vue core, a JS built-in, or already present. If any task finds it needs a new dependency it stops and routes through the Package Legitimacy Gate with a blocking human checkpoint before installing |
|
||||
</threat_model>
|
||||
|
||||
<artifacts_this_phase_produces>
|
||||
## Artifacts this phase produces
|
||||
|
||||
New symbols and paths created by Phase 02. Newly-created names below are not pre-existing
|
||||
API and must not be treated as drift from the current codebase.
|
||||
|
||||
**Created by this plan (02-01):**
|
||||
- `neode-ui/e2e/perf/surfaces.ts` — `SURFACES`, `type Surface`
|
||||
- `neode-ui/e2e/perf/measure.ts` — `measureSurface()`, `type SurfaceMeasurement`, `type RpcCall`
|
||||
- `neode-ui/e2e/perf/surface-perf.spec.ts`
|
||||
- `.planning/phases/02-ui-performance/02-PERF-BASELINE.json`
|
||||
- `.planning/phases/02-ui-performance/02-FINDINGS.md`
|
||||
- Environment variables consumed: `ARCHY_PERF_OUT` (new), `ARCHY_BASE_URL` (pre-existing in `playwright.config.ts`)
|
||||
|
||||
**Created elsewhere in Phase 02 (for cross-plan reference):**
|
||||
- `neode-ui/src/views/dashboard/keepAliveRoutes.ts` — `shouldKeepAlive()`, `KEEP_ALIVE_PATHS`
|
||||
- `neode-ui/src/components/RefreshIndicator.vue`
|
||||
- `neode-ui/src/composables/__tests__/useCachedResource.test.ts`
|
||||
- `neode-ui/src/views/dashboard/__tests__/keepAliveTabs.test.ts`
|
||||
- `RouteMeta.keepAlive` — `vue-router` module augmentation
|
||||
- `.planning/phases/02-ui-performance/02-PERF-AFTER.json`
|
||||
</artifacts_this_phase_produces>
|
||||
|
||||
<assumptions_and_flagged_items>
|
||||
## Assumptions & Flagged Items
|
||||
|
||||
Nothing below is silently dropped. Each row is an explicit flagged assumption carried into
|
||||
execution.
|
||||
|
||||
### Edge-coverage probe rows (spec-less fallback — all three came back unclassified/unresolved)
|
||||
|
||||
| Requirement | Probe status | Disposition here |
|
||||
|---|---|---|
|
||||
| PERF-01 | `unclassified` / `unresolved` — probe could not classify | FLAGGED. Not auto-backstopped. Resolved in substance by the `must_haves.truths` written above (measured-cause coverage, closed cause set, doc-before-fixes ordering, unmeasured-is-not-fast), plus one `verification: backstop` truth for run-to-run classification stability. The probe row itself remains unresolved and is surfaced here for human review. |
|
||||
| PERF-02 | `unclassified` / `unresolved` | FLAGGED and carried in plans 02-02, 02-04, 02-05, 02-06, 02-07, 02-08. |
|
||||
| PERF-03 | `unclassified` / `unresolved` | FLAGGED and carried in plans 02-03 and 02-08. |
|
||||
|
||||
### Prohibition-probe canon referrals (breadcrumbed, deliberately not minted)
|
||||
|
||||
- Injection / XSS via cached-then-rendered payloads is canon — covered by `/gsd-secure-phase` and eslint security plugins; not minted here.
|
||||
- Generic GDPR / data-retention rules for browser storage are canon — covered by `/gsd-secure-phase`; the privacy prohibitions minted in this phase are product-specific payload classes (wallet, credential, peer-content), not the generic rule.
|
||||
|
||||
### Corrections to prior phase artifacts
|
||||
|
||||
| ID | Item | Evidence | Impact |
|
||||
|---|---|---|---|
|
||||
| FA-B | `neode-ui/src/views/ContainerAppDetails.vue` appears to be dead code — `grep -rn "ContainerAppDetails" neode-ui/src` returns only a self-referential comment inside the file itself, and the file has no entry in `neode-ui/src/router/index.ts` | Verified 2026-07-30 by this planner | RESEARCH.md names it as the *confirmed* serial-waterfall fix target. If dead, no plan should spend effort on it. Task 3 re-runs the grep and records the verdict. |
|
||||
| FA-F | CONTEXT.md `canonical_refs` names `neode-ui/src/App.vue` as the KeepAlive insertion point | RESEARCH.md Pitfall 2, confirmed by this planner reading `Dashboard.vue:87-118` | Superseded — the real per-tab remount point is the nested `RouterView` in `Dashboard.vue`. Carried into plan 02-02. |
|
||||
</assumptions_and_flagged_items>
|
||||
|
||||
<verification>
|
||||
- `npx playwright test e2e/perf/surface-perf.spec.ts --project=chromium` exits 0
|
||||
- `.planning/phases/02-ui-performance/02-PERF-BASELINE.json` covers every `SURFACES` row
|
||||
- `.planning/phases/02-ui-performance/02-FINDINGS.md` has all six required headings and is committed
|
||||
- `git diff --name-only <plan-start>..HEAD -- neode-ui/src` is empty — the D-10 ordering held
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- Every D-09 surface has a measured first-visit and revisit number taken against archi-dev-box (or an explicitly labelled fallback target)
|
||||
- Every surface has exactly one primary cause from the closed set, each backed by a cited baseline field
|
||||
- The findings doc is committed before any `neode-ui/src` change in this phase
|
||||
- The harness can be re-run later to produce a directly comparable after-artifact
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
Create `.planning/phases/02-ui-performance/02-01-SUMMARY.md` when done. Include the
|
||||
per-surface cause table and the ranked fix order verbatim — downstream plans read the
|
||||
tracer-tab selection from it.
|
||||
</output>
|
||||
Reference in New Issue
Block a user