docs/reference/completion.md walks every item: the 55 from IMPLEMENTATION.md section 6 and the 10 from decisions-2026-08-18.md. For each: status, the task that delivered it, the probe that re-verifies it on every run, and every deviation from written acceptance criteria - B7's page-not-merge (measured), CR-014's email body (the no-customer-IP rule won), CR-008's merge-vs-list (recommended, not decided), F6's 2.17-vs-2.0 (BL-022), S1's residual 21 dialogs (BL-024). The four out-of-scope items are confirmed unbuilt - two of them by probes that grep for their fields on every run. Section 8's outstanding inputs are restated (the material workbook and the B100 list still have not arrived; both upload paths are ready). The follow-ups for the next revision are in one place, including three product questions raised in commit messages along the way and the acceptance criteria that turned out wrong, for calibration. One item in the whole plan is knowingly open: S13 (seed_demo sign-in), carried with a reason, and F6's last number awaits a product answer. Wave 9 exit criteria: seven of seven, ticked with their verifying probes. Items: all Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
317 lines
14 KiB
Markdown
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
|
|
|
|
- [x] the export matches the final structure (`export_check.py`, 20 checks — required fields present, CR-002 removals absent, CR-006 suppression honoured, tablet-legible)
|
|
- [x] one icon system, one sample-data affordance (`icon_check.py`, `sample_check.py`)
|
|
- [x] accessibility metrics hit target or are documented (`docs/reference/accessibility-audit.md`; the one gap — 21 dialogs on surfaces no S1 task named — is BL-024)
|
|
- [x] the primary flow works at 390px (`mobile_check.py`, 24 checks, all seven pages; screenshots committed)
|
|
- [x] archived projects are readable by project admins and invisible to everyone else (`archived_check.py`, 15 checks)
|
|
- [x] the backlog has no entry still pointing at wave 9 (nine closed at T9.9, each with its measurement)
|
|
- [x] every item is reconciled — all 65 (`docs/reference/completion.md`)
|