First field-visible wave. Waves 1-4 moved almost nothing on screen; every page in this one looks different. Baseline counts, against wave 0 <div onclick> 12 -> 2 (T5.1 took exactly ten) native dialogs app-wide 79 -> 64 (T5.1 2, T5.2 1, T5.8 13) ...in the SOP wizard 14 -> 0 ...in the creator 43 -> 43 wave 7's colour literals outside theme-light.css 0 -> 0, held SOP wizard steps 10 -> 12 (T5.4 Locations, T5.5 Sections) Six probes now cover this wave, 399 checks between them, each written because its task's done-when could not be checked by anything that already existed. Screenshots re-captured at 390 and 1440 across all seven pages. One overflow, the known creator@390 (BL-001), unchanged. The two beforeunload log lines on sop@1440 and creator@1440 are present at wave 4 too - captured both sides during T5.1 rather than assuming. BL-010 is honestly unchanged: every rule wave 5 added consumes --wp-s*, and none of the 829 pre-existing spacing/type/radius literals were converted, because none of the pages carrying them were re-laid-out here. T7.1 still owns it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
13 KiB
Wave 5 — Launcher and SOP wizard
Items: A4, B3, S9, S1 (wizard), CR-005, CR-006, CR-002, CR-016
Depends on: wave 4 merged
Why here: CR-006 is the enabler for every removal request in the plan. Building it
before CR-002 and CR-016 means nothing gets deleted that another project may need.
First field-visible wave. Everything before this was prerequisites.
T5.1 — A4 + S9: Vertical stepper with real buttons
- Items:
A4,S9 - Depends on: T3.4, T3.5, T2.2
- Blocks: T5.4, T5.5
- Surface:
html/ - Files: SOP wizard step rail
Problem: The step rail is 10 <div> elements with onclick, so it is unreachable by
keyboard. There is also an orphaned "1 / 10" counter doing the job a stepper should do.
Do: Rebuild the rail as a vertical stepper showing all 10 steps, which is complete, which
is current, and which are not yet reachable. Every step is a real <button>. Retire the
"1 / 10" counter.
Per C1, this is the moment to make it accessible — it is being rebuilt anyway.
Do not: ship a single <div onclick> in the replacement. The app-wide count from wave 0
must go down by 10.
Done when:
- all 10 steps are
<button>elements - the rail is fully operable by keyboard: tab, arrow keys, enter and space
- current step is exposed with
aria-current - completed, current and unavailable states are distinguishable without relying on color alone
- the "1 / 10" counter is gone
- app-wide
<div onclick>count dropped by 10 versus the wave 0 baseline
T5.2 — B3: Launcher empty state, then remove the picker card
- Items:
B3 - Depends on: T4.1
- Blocks: T5.3
- Surface:
html/ - Files: launcher, project picker card
Problem: The proposal removes the project-picker card, but the first-run empty state lives inside it. A header dropdown is the wrong home for "create your first project".
Do: Build an explicit first-run empty state on the launcher: no projects yet, here is how to create one, here is the sample project. Only once that exists, remove the picker card. Order matters — removing the card first strands new users.
Done when:
- a brand-new account with zero projects sees a clear path to create one
- the sample project remains discoverable from the empty state
- the picker card is removed only after the empty state ships
- switching projects still works from the header for users who have projects
T5.3 — B4 surface: pipeline strip
- Items:
B4UI half - Depends on: T4.1, T5.2
- Blocks: nothing
- Surface:
html/ - Files: launcher
Do: Build the four-cell pipeline strip against the server aggregates from T4.1. Each
cell links through to the filtered list, using the URL state from T4.2.
Do not: ship it against localStorage. That is the specific thing B4 warns about.
Done when:
- every number comes from a server endpoint
- each cell links to a filtered view via a shareable URL
- a project with zero work packages renders a sensible empty state, not four zeros that look broken
- the strip announces updates via
aria-liveif it refreshes in place
T5.4 — CR-005: Upload building / floor / sector lists at SOP setup
- Items:
CR-005 - Depends on: T5.1
- Blocks: T6.3
- Surface:
server/+html/ - Files: SOP wizard, server API, schema
Intent: The location taxonomy differs per project. On Micron, floors within B100 behave like separate buildings, so floor and sector are the unit of both execution and cost tracking. Configure it once per SOP rather than hard-coding it.
Do: A wizard step accepting a bulk upload (CSV or paste) of Building / Floor / Sector
values, with the hierarchy preserved. Editable after import: add, rename, deactivate. Store
as structured codes, not display strings — CR-018 needs to group by them.
Deactivating a value hides it from new work packages without breaking existing ones that reference it.
Do not: hardcode floor or building names. The B100 list has not been supplied yet (see
IMPLEMENTATION.md section 8). Seed with obviously-fake sample values.
Done when:
- CSV upload and paste both work and report rejected rows with reasons
- duplicates are detected and reported rather than silently merged
- values are editable after import
- deactivating a value hides it from new work packages; an existing work package referencing it still renders
- values are stored as codes suitable for grouping
- no guessed real-world floor names exist anywhere in the code
T5.5 — CR-006: Section toggles
- Items:
CR-006 - Depends on: T5.1
- Blocks: T5.6, T5.7, T7.2
- Surface:
server/+html/ - Files: SOP wizard, work package renderer, PDF export, creator
Intent: This is the structural fix behind most removal requests in the plan. Rather than deleting fields globally, each project turns on only the sections it uses. It is what lets Micron drop Kitting and Assets while another project keeps them.
Do: In the SOP creation tool, list every work package section with an on/off toggle: General Information, Location, Scope of Work, Assets, Materials, Kitting, Drawings and Attachments, Constraints, QA/QC, Closeout. Default all on for a new SOP.
A section toggled off does not render in the creation form, the detail view, or the PDF export. Data already captured is retained, and toggling back on restores it intact.
Do not: delete data on toggle-off. Ever. And note X4: the creator is an iframe child
until T7.1, so toggle propagation into the creator may need revisiting in wave 7 — test it
and say what you found.
Done when:
- all 10 sections are toggleable
- a section toggled off is absent from the form, the detail view and the PDF export
- toggling off then on restores prior data with no loss
- new SOPs default to all sections on
- toggle state propagates into the creator, or the PR documents exactly where it does not and why
T5.6 — CR-002: Remove Acumatica Cost Code and Task
- Items:
CR-002 - Depends on: T5.5
- Blocks: nothing
- Surface:
html/+server/ - Files: work package form, detail view, PDF export
Intent: The team concluded these are noise on a field work package. Cost codes are
effectively constant and the Acumatica task mapping is a PM concern. The cost visibility they
actually want is by building and floor, which is CR-004 and CR-018.
Do: Hide both fields from the form, the detail view and the PDF export, using the section
or field toggle mechanism from T5.5. Retain the data and the model.
Do not: drop the columns or delete the data. Another project may need these fields, and that is what the toggles are for.
Done when:
- neither field appears in the form, detail view or PDF export for the Micron EUV SOP
- existing records still hold their values; confirm by querying
- the fields can be re-enabled for another SOP without a code change
- no schema migration drops data
T5.7 — CR-016: Assets section off for Micron EUV
- Items:
CR-016 - Depends on: T5.5
- Blocks: nothing
- Surface: configuration
- Files: SOP configuration for Micron EUV
Intent: Asset content duplicates the database Clinton's team maintains. Integration is deferred, so the section comes out in the interim.
Do: Toggle Assets off for the Micron EUV SOP. Leave the section and its data model in the application so the eventual database integration has somewhere to land.
Done when:
- Assets does not render for Micron EUV in the form, detail view or export
- the section and model remain in the codebase
- another SOP can enable Assets and it works
T5.8 — S1 (wizard): Inline validation
- Items:
S1wizard half - Depends on: T5.1
- Blocks: nothing
- Surface:
html/ - Files: SOP wizard validation,
wp-creation-app.js:1144for the pattern to replace
Problem: Validation is alert()-only and validateStep guards only steps 1, 5 and 6,
while the markup marks required fields throughout. The message "Subject and WP Type are
required" names no field, highlights nothing and scrolls nowhere.
Do: Inline validation on every step that has required fields. Errors appear at the field,
the first invalid field receives focus, and the message says what is wrong. Announce via the
aria-live region from T4.5. Remove the wizard's alert() calls.
Do not: add a native alert(), confirm() or prompt() anywhere. The app-wide count
from wave 0 must go down.
Done when:
- every step with required fields validates them
- each error renders at its field and is associated via
aria-describedby - submitting an invalid step focuses and scrolls to the first error
- errors announce to screen readers
- the wizard's native dialog count is 0; record the new app-wide count
Wave 5 exit criteria
- the stepper is keyboard operable and
<div onclick>count dropped by at least 10 — 12 → 2, exactly ten, and the two survivors are wave 7's and wave 9's - section toggles work end to end, including the export
- Acumatica fields and Assets are hidden by configuration, with no data deleted
- the wizard has no
alert()calls left — 0, raw and comment-stripped - first-run users can create a project
Wave 5 exit — what shipped, and what it cost
First field-visible wave. Everything before this was prerequisites, and the difference shows: waves 1–4 moved almost nothing on screen, and every page in this one looks different.
The tasks
| Task | Items | What landed |
|---|---|---|
T5.1 |
A4 S9 |
Vertical stepper, ten real <button>s, keyboard operable, states in words |
T5.2 |
B3 |
First-run empty state, then the picker card removed; switching moved to the app bar |
T5.3 |
B4 UI |
Four-cell pipeline strip, every number from the server, every cell a shareable link |
T5.4 |
CR-005 |
Per-project Building / Floor / Sector taxonomy — new table, four routes, step 11 |
T5.5 |
CR-006 |
Section toggles, shared registry, form + detail view + export |
T5.6 |
CR-002 |
Acumatica cost code and task, hidden by field toggle |
T5.7 |
CR-016 |
Assets off for Micron EUV, by configuration |
T5.8 |
S1 wizard |
Inline validation on five steps; thirteen native dialogs retired |
Baseline counts
| Metric | Wave 0 | End of wave 5 | Moved by |
|---|---|---|---|
<div onclick> |
12 | 2 | T5.1 |
| native dialogs app-wide | 79 | 64 | T5.1 (2), T5.2 (1), T5.8 (13) |
| …of those, in the SOP wizard | 14 | 0 | T5.8 |
| …of those, in the creator | 43 | 43 | wave 7 |
colour literals outside theme-light.css |
0 | 0 | held |
| SOP wizard steps | 10 | 12 | T5.4, T5.5 |
Probes added
Five, each written because its task's done-when could not be checked by anything that already existed. Run them one at a time.
python tests/stepper_check.py # A4/S9 71 checks
python tests/launcher_check.py # B3 58 checks (two seeded databases)
python tests/pipeline_check.py # B4 UI 43 checks
python tests/locations_check.py # CR-005 58 checks
python tests/sections_check.py # CR-006/CR-002/CR-016 88 checks
python tests/validation_check.py # S1 81 checks
The four things the probes caught that a review would not have
T5.1— the rail did not track the form. Fill step 1 and every step ahead stayed padlocked until you navigated. A rail that lies about the form is worse than the strip it replaced, because that one at least lied consistently.T5.2—f_items.py'sF1wentINCONCLUSIVE, notFAIL. Its probe drove the picker card's<select>, whichB3deleted. It refused to guess, which is the behaviourf_itemsexists for.T5.3— a pipeline link landed on "complete the SOP first". Not the strip's fault:browser_check's fixture stores a SOP shape production never writes. Logged as BL-018.T5.6— a probe reported the cost code being eaten by a section toggle. It was not; the probe used an invented code andwp_costis a<select>that silently drops an unknown value. That silent drop is real, is not this wave's, and is BL-019.
Open, carried into wave 6 and beyond
- BL-010 (raw spacing and type values) is unchanged. Every rule wave 5 added
consumes
--wp-s*; none of the 483/281/65 pre-existing literals were converted, because none of the pages carrying them were re-laid-out here.T7.1still owns it. - X4 is resolved rather than deferred — see
T5.5's commit. The SOP-borne propagation path is unaffected byB7; the live hand-off across the frame is whatT7.1removes. - BL-018 (the WP tab's gate is the last
localStorage-derived status) is the one finding in this wave that is a real user-facing weakness rather than a test artefact.