The plan was delivered as wp-suite-implementation-spec.zip and lived only in Downloads, so every "read CLAUDE.md first" instruction in it pointed at a file the repo did not have. Bring it in unchanged: CLAUDE.md, IMPLEMENTATION.md, and docs/waves/wave-0 through wave-9 plus backlog.md. UX-REVIEW-2026-08-14.md is committed alongside it. It is the review that produced F1-F6, S1-S13 and the A/B/C assessments, and item IDs throughout the wave files cite it, so it belongs under version control rather than sitting untracked in the working tree. No application code changes here. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
7.1 KiB
Wave 1 — Rendering defects and tooling
Items: F1, F2 (interim), F3, F4, F5 (interim), S13
Depends on: wave 0
Why first: none of these need a design decision, and F1 and F2 block all chrome work
in wave 2.
Two tasks here are deliberately partial. F2 gets a containment fix only because B1 in
wave 2 resolves it properly, and F5 gets a one-line fix because C3 in wave 3 removes the
underlying cause. Do not over-build either.
T1.1 — F1: Header project switcher is stale on every page
- Items:
F1 - Depends on: T0.1
- Blocks: T2.1, T2.2
- Surface:
html/ - Files: per file-map — the app bar/header component and whatever holds active-project state
Problem: The hero, the project picker and the create-user card all show the active project. The app bar still reads "Select a project". Two sources of truth for the same value, and the global one loses.
Do:
Find every place the active project is read or stored. There is more than one. Collapse them to a single source, and have the app bar subscribe to it rather than holding its own copy. Set the value on project selection and on page load, including a hard refresh and a deep-linked page.
Do not: introduce a state library. This is a single value with a small number of readers.
Done when:
- the app bar shows the active project on all 6 pages
- value survives a hard refresh on every page
- switching projects updates the app bar and the hero in the same interaction, with no reload
- with no project selected, the app bar reads "Select a project" and the picker is reachable
- exactly one code path writes active-project state; note its location in the PR
T1.2 — F2 (interim): stop the app bar clipping at 390px
- Items:
F2partial - Depends on: T1.1
- Blocks: nothing (superseded by T2.2)
- Surface:
html/ - Files: app bar styles
Problem: At 390px the nav wraps to three rows and clips. "Sign out" is cut in half and search is truncated. Field View runs at this width on tablets with gloved hands.
Do: The smallest change that guarantees no control is unreachable or visually cut. Allow
the bar to scroll or stack rather than clip. This is triage, not a redesign — T2.2 deletes
this markup.
Do not: build a responsive menu, a hamburger, or an avatar dropdown. Wave 2 ships the existing drawer instead, and anything built here would be thrown away.
Done when:
- at 390px no nav control is clipped or unreachable on any of the 6 pages
- "Sign out" is fully visible and tappable at 390px
- search is either fully usable or deliberately hidden at this width, not truncated
- no layout change at 1440px — screenshot diff against baseline is empty
- the PR states this is interim and names
T2.2as the real fix
T1.3 — F3: Logo and project name collide in the SOP header
- Items:
F3 - Depends on: T1.1
- Blocks: nothing
- Surface:
html/ - Files: SOP wizard page and its header styles,
.header-left
Problem: .header-left and the injected chrome compete for the same run of the bar and
overlap.
Do: Give the two elements a defined relationship rather than letting both claim the same space. Verify with a long project name — "Micron EUV Cleanroom Enable 2667008" is the real one and it is what breaks things.
Do not: solve it by truncating the project name. B2 in wave 2 owns truncation and
needs a breakpoint plan, not a silent ellipsis.
Done when:
- no overlap at 390px, 768px, 1024px and 1440px
- tested with the longest real project name
- the logo remains fully visible at all four widths
T1.4 — F4: Comments drawer renders off-screen over the header
- Items:
F4 - Depends on: T0.1
- Blocks: nothing
- Surface:
html/ - Files: standalone creator page and comments drawer styles
Problem: In the standalone creator, the comments drawer renders off-screen and over the header.
Do: Fix the positioning context and stacking. Check whether the drawer is positioned
relative to the iframe or the parent — if the iframe boundary is implicated, note it in the
PR because T7.1 removes that boundary.
Do not: raise z-index until something happens to work. Identify the containing block
first and say what it was in the PR.
Done when:
- the drawer opens fully on screen in the standalone creator at 390px and 1440px
- the drawer does not cover the header
- the drawer closes and reopens correctly, and scroll position is not lost
- behavior is identical in the embedded and standalone creator
T1.5 — F5 (interim): SOP wizard fields read as read-only
- Items:
F5partial,A3partial - Depends on: T0.1
- Blocks: nothing (completed by T3.4)
- Surface:
html/ - Files: SOP wizard stylesheet
Problem: Wizard inputs render with a #f4f4f4 fill and #e0e0e0 border, which reads as
disabled. Users do not type in them. The cause is that the wizard redeclares its own tokens
and never sees --cds-field: #ffffff.
Do: Make the fields look editable. The minimal correct fix is to have the wizard consume the existing field token instead of its local override.
Do not: start token consolidation here. That is T3.1–T3.3 and it is a separate,
mechanical, whole-app change. Fix the field appearance only.
Done when:
- wizard inputs render with a white fill and a border visually consistent with inputs elsewhere
- genuinely disabled inputs still look disabled and are distinguishable from enabled ones
- no other component changes appearance — screenshot diff limited to the wizard
- the PR notes that
T3.4removes the underlying duplicate token
T1.6 — S13: server/seed_demo.py cannot seed a running instance
- Items:
S13 - Depends on: T0.1
- Blocks: nothing, but makes every later task's setup faster
- Surface:
server/ - Files:
server/seed_demo.py, and the smoke test for reference
Problem: Every /api/ route requires a session and the script sends none, so it cannot
seed a running instance. It predates the commit that taught the smoke test to sign in.
Do: Give the script the same authentication the smoke test uses. Reuse that code path rather than writing a second one.
Do not: add a bypass, a debug flag, or an unauthenticated seeding route to the server. The script authenticates like a client; the server does not get weaker.
Done when:
seed_demo.pyruns against a freshly started instance and exits 0- the seeded data is visible in the UI after running it
- running it twice does not error or duplicate data, or it fails with a clear message
- no new unauthenticated route exists — confirm by diff
Wave 1 exit criteria
F1,F3,F4fully resolved and confirmed against the wave 0 baseline screenshotsF2andF5contained, with their real fixes referenced (T2.2,T3.4)S13fixed and seeding works- no new
<div onclick>, no new raw hex values, no newalert()calls introduced F6untouched — it is a structural problem fixed by section tabs inT7.2