Files
Project-SDE-WP-Suite/docs/waves/wave-9.md
n.siegfried 0dbc240900 Wave 7 prep - record the Aug 18 decisions as D1-D10 and amend the waves
Nick answered 21 questions at the wave 6 exit and 11 follow-ups. Seven answers
are new build work, three amend acceptance criteria on tasks already scheduled,
and two close questions without work. None of it had an item ID, so none of it
could be built under CLAUDE.md's first rule.

New items D1-D10 in docs/waves/decisions-2026-08-18.md. A new prefix rather than
widened CR/F/S/A/B/C numbers - those are referenced in documents outside this
repo and CLAUDE.md forbids reinterpreting them. Every D entry names the item it
amends and quotes the criterion it replaces, so a reader of R2 can see what moved.

  D1  sample data returns to the creator                    B7, S7   T7.1
  D2  QA distribution list configured in the SOP            CR-014   T7.6
  D3  side navigation and collapsible sections, not tabs    F6       T7.2
  D4  Urgent surfaces the audited override, never bypasses  CR-003/A1 T7.3
  D5  usage data moves to the admin console                 B7       T7.10 (new)
  D6  material list uploads at SOP configuration            CR-013   T8.6  (new)
  D7  archived projects readable by project admins          B3, C1   T9.8  (new)
  D8  5MB a file, 2GB a project, PDFs and images, one DB    CR-007   T7.7
  D9  Ready for QA appears in Field View                    CR-014   T7.6
  D10 email switched on and off from the admin console      CR-011/14 T7.6, T8.3

Two decisions were mine to make and are recorded as such. D3: the written F6
criterion (no view over two screen heights) and the answer (one long form with
side nav) cannot both hold, so the criterion now reads 'at rest' and sections
collapse by default - tabs hide sections a first-time author does not know exist.
D8: keeping 5MB files in the same database means every encrypted backup carries
them; splitting them out was rejected because a backup without the drawings
cannot restore, so a 2GB per-project ceiling was approved instead.

Also corrected, not amended: CLAUDE.md and IMPLEMENTATION.md X2 both cited
wp-creation-app.js:1962-1972 as the protected logged-override path that T7.3 is
forbidden to remove. Those lines are deletePackage() and clearSaved(). The path
is confirmEarlyRelease() at :1002. Both documents now name it by function so the
reference survives the T7.1 rewrite that is about to move it.

Wave 9 gains T9.9, a sweep of the nine backlog entries that name wave 9 as their
home. Left unscheduled they surface at T9.7, which has no room to fix anything.
The four colour items in it (BL-004/005/008/009) are now approved work.

T9.5's help-tip count corrected from 15 to 18 and dated: three were added during
waves 5 and 6 by tasks reusing the component as designed, each unreachable for
the same reason. Scheduling a broken component late makes every reuse cost more.

Closed without work: the free-text location migration. Every location on record
is sample data because no real list has been loaded, so there is nothing to
migrate. Recorded with the condition that invalidates it - the first real
project - so it is a decision rather than a surprise.

Items: D1 D2 D3 D4 D5 D6 D7 D8 D9 D10
Task: T7.0 (wave 7 prep)

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 13:29:58 -05:00

317 lines
14 KiB
Markdown

# Wave 9 — Verification and cleanup
**Items:** `CR-008`, `CR-017` (guard), `S6`, `S7`, `S8`, `C1` audit, `C2` audit, part of `C4`,
and from August 18: `D7`
**Depends on:** wave 8 merged
**Build order is not task order.** `T9.8` and `T9.9` were added on August 18 and are numbered
after `T9.7`, but `T9.7` is the reconciliation and stays last. Build `T9.1` through `T9.6`,
then `T9.8`, `T9.9`, then `T9.7`. They appear in that order in this file. Task IDs are
referenced outside this repo and are not renumbered to make the order read left to right.
**Why last:** `CR-008` reviews the PDF export against the final structure rather than
reviewing it twice. The audits confirm the standing requirements actually held across eight
waves rather than being asserted per PR.
---
### T9.1 — CR-008: PDF export review
- **Items:** `CR-008`
- **Depends on:** T8.5
- **Blocks:** nothing
- **Surface:** `server/` + `html/`
- **Files:** PDF export
**Problem:** The export was never walked through in the meeting. It needs a pass to confirm
it prints what the field actually needs and nothing it does not, now that the work package
structure has changed substantially.
**Do:** Review the export section by section against the final structure. Sections toggled
off under `CR-006` must be omitted. The export must include: P6 Activity ID and Description,
Priority, Building / Floor / Sector, scope of work, materials, constraints with status,
QA/QC, and an attachment index. Removed fields — ACU Cost Code, Acumatica Task — must not
appear.
Open question to raise in the PR, not to decide alone: should attachments merge into a single
PDF package, or be listed as separate files? The field preference expressed in the meeting
was to hand someone exactly the sheet they need and nothing more, which argues for a merged
package with only the attached sheets. Propose, do not assume.
**Done when:**
- [ ] every listed field appears in the export
- [ ] toggled-off sections are absent
- [ ] ACU Cost Code and Acumatica Task appear nowhere
- [ ] the export is legible printed in black and white
- [ ] the export is legible opened on a tablet
- [ ] the attachment index lists every attachment with its description
- [ ] the merge-versus-list question is raised in the PR with a recommendation
---
### T9.2 — CR-017: Actual Hours guard
- **Items:** `CR-017`
- **Depends on:** T9.1
- **Blocks:** nothing
- **Surface:** verification only
- **Files:** Closeout section
**This is a guard, not a build.** Removing Actual Hours was floated in the meeting and
rejected — Marlena said she likes tracking actual hours spent so it can be measured. It is
listed here so a later simplification pass does not quietly drop it.
**Do:** Confirm Actual Hours still exists in Closeout, is optional rather than required, and
survived eight waves of change.
**Done when:**
- [ ] Actual Hours exists in Closeout and persists
- [ ] it is optional, and a work package can be closed without it
- [ ] it rolls up per `T6.4`
- [ ] a follow-up item is logged for comparing actual against estimated hours to produce a productivity factor
---
### T9.3 — S6: One icon system
- **Items:** `S6`
- **Depends on:** T9.1
- **Blocks:** nothing
- **Surface:** `html/`
- **Files:** every page
**Problem:** The icon set mixes emoji and dingbats, and at least one glyph is used for two
different meanings on the same page.
**Do:** Pick one icon system and convert everything to it. Build a mapping of meaning to icon
and record it in `docs/reference/tokens.md`. Resolve every duplicate meaning.
**Do not:** leave emoji in the UI. They render differently per platform, which is part of why
the same glyph reads as two things.
**Done when:**
- [ ] one icon system across all 6 pages
- [ ] no glyph carries two meanings anywhere
- [ ] every icon has a text label or an accessible name
- [ ] the meaning-to-icon mapping is documented
- [ ] icons render identically on Windows, macOS and a tablet
---
### T9.4 — S7: Sample-data cleanup
- **Items:** `S7`
- **Depends on:** T9.1
- **Blocks:** nothing
- **Surface:** `html/` + `server/`
- **Files:** every sample-data affordance
**Problem:** Four sample-data affordances under three names. One sits a single click from
live project data with no confirm and no undo.
**Do:** Reduce to one affordance with one name. Move it away from live project actions. Add a
confirmation stating exactly what will happen, and make it reversible or clearly scoped to a
sample project only.
**Done when:**
- [ ] exactly one sample-data affordance exists, under one name
- [ ] it is not adjacent to any live project action
- [ ] it confirms before acting, naming what it will do
- [ ] it cannot touch live project data; verify by attempting it against a real project
- [ ] the other three affordances are removed; grep confirms
**Reconciled with `D1`.** `T7.1` makes the creator's sample-data control **visible** - it was
hidden only because the page was framed. That is not a fourth affordance returning; it is the
one that should survive becoming reachable. This task still ends with exactly one, and if the
survivor is the creator's, the launcher and wizard copies go.
---
### T9.5 — C1 + S8: Accessibility audit
- **Items:** `C1`, `S8`
- **Depends on:** T9.3
- **Blocks:** nothing
- **Surface:** `html/`
- **Files:** all pages, `.help-tip` elements
**`S8` is finished here** because tooltips are the one accessibility item with no natural
host component earlier in the plan. `.help-tip` badges are `<span>` elements with no
`tabindex`, so the `:focus` half of their CSS rule is dead code and there is no touch path at
all - on tablets, which is exactly what Field View targets.
**The count went up, not down.** Wave 0 measured 15. At the wave 6 exit there were **18**:
three were added during waves 5 and 6 by tasks reusing the component as designed, and every
one of them is unreachable for the same reason. That is the cost of scheduling a broken
component late - each wave that reuses it makes this task bigger. Measure again before
starting and record the number; do not inherit 15 or 18.
**Do:** Make every `.help-tip` reachable by keyboard and by touch. Then audit the whole app
against the `CLAUDE.md` rules and record results in `docs/reference/accessibility-audit.md`.
Compare against the wave 0 baseline counts:
| Metric | Baseline | Target |
|---|---|---|
| `<div>` / `<span>` with `onclick` | 12 / 2 | 0 |
| `.help-tip` unreachable by keyboard | 15 at wave 0, 18 at the wave 6 exit | 0 |
| `aria-live` regions | 0 | at least 1 per toast system and banner |
| Text below 4.5:1 | present | 0 |
| `outline: none` without replacement | present | 0 |
| Native dialogs (`alert`/`confirm`/`prompt`) | 79 | 0, or documented exceptions |
**Done when:**
- [ ] every `.help-tip` works by keyboard and by touch
- [ ] every metric above meets target, or the gap is documented with a reason and a follow-up item
- [ ] a full keyboard-only pass completes the primary flow: sign in, create project, SOP wizard, create work package, issue it
- [ ] the audit document exists with per-page results
---
### T9.6 — C2: Mobile pass
- **Items:** `C2`
- **Depends on:** T9.5
- **Blocks:** T9.8
- **Surface:** `html/`
- **Files:** all pages
**Problem:** Nothing in the original proposal touched mobile, and it is where the worst
rendering was found. Field View at 390px is the gloved-hands surface.
**Do:** A deliberate pass at 390px across all 6 pages and the full primary flow. Capture
after screenshots and compare against the wave 0 baseline.
**Done when:**
- [ ] the full primary flow completes at 390px without horizontal scrolling
- [ ] tap targets are at least 44px throughout
- [ ] no control is clipped, overlapped or unreachable on any page
- [ ] `CR-007` attachments open at 390px, offline
- [ ] `T8.5` material requests can be raised at 390px
- [ ] after screenshots for all 6 pages at 390px are committed alongside the baseline
---
### T9.8 — D7: Archived projects, readable by project admins
- **Items:** `D7`
- **Depends on:** T9.6
- **Blocks:** T9.7
- **Surface:** `server/` + `html/`
- **Files:** launcher project list, project routes, role checks
**Problem:** Archiving already exists for projects and for work packages, and the server
already refuses writes to an archived project. What does not exist is a way back in: an
archived project leaves the launcher and there is no route to it, so archiving reads as
deletion to everyone using it. Asked on August 18 who should be able to open one, the answer
was **project admins only**.
**Do:** List archived projects behind a role check, separately from the live list so nobody
opens one by accident. Opening one renders read-only. The server is the enforcement point:
the read-only view is a courtesy, the role check and the write refusal are the rule.
**Do not:** build a second archive mechanism, add an unarchive button, or show archived
projects to anyone below project admin - including in counts, pickers or aggregate totals
where the number would leak their existence.
**Done when:**
- [ ] a project admin can list archived projects and open one
- [ ] everything in the opened project renders read-only, with no reachable write control
- [ ] the server refuses writes to it regardless of what the browser sends; verify by calling the endpoint directly
- [ ] a non-admin sees no archived projects anywhere, including in counts and pickers
- [ ] the archived list is visually distinct from the live list and says what it is
- [ ] it works at 390px
---
### T9.9 — Backlog sweep: the items wave 9 was told to own
- **Items:** `C4`, plus `BL-004`, `BL-005`, `BL-008`, `BL-009`, `BL-011`, `BL-012`, `BL-016`, `BL-018`, `BL-019`
- **Depends on:** T9.5
- **Blocks:** T9.7
- **Surface:** `html/` + `tests/`
- **Files:** as listed per entry in `docs/waves/backlog.md`
**Why this is a task and not a list.** Nine backlog entries name wave 9 as their home. Left
unscheduled they get discovered at `T9.7`, which is a reconciliation task with no room to fix
anything. Each was deferred for a stated reason and every one of those reasons has now
expired.
**The four colour items are approved work, not open questions.** `BL-004` (the help centre's
separate 52-colour palette, loaded on four pages), `BL-005` (35 colour literals in two
JS-built dialogs), `BL-008` (a second brand blue, `#2563d6`) and `BL-009` (a ninth amber, four
points from the eighth) were each deferred on the same grounds: fixing them changes a rendered
colour and the wave that found them was forbidden to change one. Asked on August 18, the
answer was **change them**. That is the `C4` half of this task and it is the only part with a
visible diff.
The rest are correctness and tooling:
| Entry | What it is | Note |
|---|---|---|
| `BL-011` | Three overlays race to append on the SOP page | Re-check first - `T7.1` may have removed the cause |
| `BL-012` | `admin` and the creator are not stable enough to screenshot-diff | Freeze the clock in the fixture; the creator half may be gone after `T7.2` |
| `BL-016` | Back to a URL with no `step` leaves the wizard where it was | One expression. `stepper_check.py` already pins the wrong behaviour, so the test flips with the fix |
| `BL-018` | The work package gate is the last localStorage-derived status | `T7.1` may have resolved it; if not, it is `B4`'s last hole. Fix `browser_check.py`'s fixture either way |
| `BL-019` | A cost code that left the list is silently blanked on edit | The four lines already written for `gov_wosize` |
**Do not:** fix anything here that a wave 7 or 8 task already fixed. Re-measure each before
touching it - four of these were logged against code that has since been rewritten, and a fix
applied to a problem that no longer exists is worse than the problem.
**Done when:**
- [ ] every colour literal outside `theme-light.css` is gone, help centre and JS-built dialogs included; grep confirms
- [ ] one accent blue and one warning amber app-wide
- [ ] each of `BL-011`, `BL-012`, `BL-016`, `BL-018`, `BL-019` is fixed, or closed with a recorded measurement showing it no longer reproduces
- [ ] `stepper_check.py`'s pinned `BL-016` check is inverted to assert the fixed behaviour
- [ ] `browser_check.py`'s fixture uses the production SOP shape
- [ ] `docs/waves/backlog.md` has no entry still pointing at wave 9
---
### T9.7 — Final reconciliation
- **Items:** all
- **Depends on:** T9.8, T9.9
- **Blocks:** nothing
- **Surface:** documentation
- **Files:** creates `docs/reference/completion.md`
**Do:** Walk all 65 items - the 55 in `IMPLEMENTATION.md` section 6 and the 10 in
`docs/waves/decisions-2026-08-18.md` and record, for each: built /
deferred / not applicable, the PR that delivered it, and any deviation from its written
acceptance criteria.
Explicitly confirm the four out-of-scope items in section 7 were not built: no parts catalog
or inventory, no asset database integration, no CxAlloy integration, no P6 activity import.
Then list what the plan learned that the next revision should carry: items whose acceptance
criteria turned out wrong, inputs still outstanding, and follow-ups logged along the way.
**Done when:**
- [ ] all 65 items are accounted for with a PR reference or a stated reason - the 55 from section 6 and the 10 from `decisions-2026-08-18.md`
- [ ] every deviation from written acceptance criteria is documented
- [ ] the four out-of-scope items are confirmed unbuilt
- [ ] outstanding inputs from `IMPLEMENTATION.md` section 8 are restated with current status
- [ ] follow-ups are collected in one place for the next revision
---
## Wave 9 exit criteria
- [ ] the export matches the final structure
- [ ] one icon system, one sample-data affordance
- [ ] accessibility metrics hit target or are documented
- [ ] the primary flow works at 390px
- [ ] archived projects are readable by project admins and invisible to everyone else (`D7`)
- [ ] the backlog has no entry still pointing at wave 9
- [ ] every item is reconciled - all 65