Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 67 additions & 10 deletions .planning/STATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,11 @@ settled. The gate earned its place; the hold was correct.
`1a32f08`. Accepted deliberately: the collapse removed a class of seam rather
than adding another guard.
- No human screen-reader pass on the person picker. axe is clean across empty and
populated states, which is not the same thing.
- 21-05 Task 5 (human browser verification) was never performed.
populated states, which is not the same thing. **Consolidated 2026-08-10 into
`todos/pending/2026-08-10-person-picker-screen-reader-pass.md`** — see the
reassessment below.
- ~~21-05 Task 5 (human browser verification) was never performed.~~ **STRUCK
2026-08-10 as superseded** — see below.

### The two carried gaps — one closed, one only narrowed (2026-08-09)

Expand All @@ -94,6 +97,34 @@ whether the live-region timing is usable, or whether the four similarly-named
groups are actually distinguishable in practice. A human with NVDA or VoiceOver
remains worthwhile, and no automated result should be read as having replaced it.

### Reassessed 2026-08-10 — the two remaining items are ONE task

Both were carried as prose here rather than as a todo, which is how they survived
two releases without moving. Reviewing them together:

**21-05 Task 5 — STRUCK as superseded.** Phase 25 performed a genuine human pass
in a live editor (`25-VERIFICATION.md`, 2026-08-09), and recorded itself as such
precisely because this project had one checkpoint recorded the other way. It
covered the toolbar and the locked-checkbox row. It did NOT cover the person
picker or the four-group popover — so the residue is real, but it is the same
residue as the screen-reader item, not a separate one.

**The screen-reader item slightly WIDENED, and now owns the residue.** Phase 25's
M2 change altered this same popover AFTER the v1.5.0 axe scan: the derived-locked
checkbox went from natively `disabled` to `aria-disabled`, so a control that
focus mode used to skip is now reachable and refuses its own toggle. That was the
right fix — the lock reason was written for assistive technology and could never
be heard while the row was skipped — but it changes tab order and announcement
sequence in exactly the component that has never had a human pass, and a
focusable-but-refusing control is not something automated tooling can evaluate
for comprehensibility. axe passes over it either way.

Both now live in `todos/pending/2026-08-10-person-picker-screen-reader-pass.md`
as one task: one person, one sitting, VoiceOver or NVDA actually running.

The original record of 21-05 Task 5 follows, kept because the distinction it
draws is the reason both were written down.

**21-05 Task 5 (human verification) — NOT PERFORMED AS SPECIFIED.** The plan
marked it `autonomous: false` and called for a person driving the real editor in
a browser before the phase closed. That did not happen. The phase was accepted
Expand Down Expand Up @@ -166,10 +197,17 @@ not automatic and required a manual `workflow_dispatch`. Plan the step in.
**Open, carried deliberately:**
- ROLE-02's cloned-role "profiles" half is still deferred
(`todos/pending/2026-08-02-cloned-role-hiding-profiles.md`)
- Phase 22 (Playground demo) and Phase 25 (toolbar polish) remain open
- The #128 fixes shipped unreviewed (the ultrareview ran against the prior commit)
- No human screen-reader pass on the person picker
- 21-05 Task 5 (human browser verification) was never performed
- Phase 22 (Playground demo) remains open. ~~Phase 25 (toolbar polish)~~ —
✅ COMPLETE 2026-08-09, SHIPPED in v1.5.1
- The #128 fixes shipped unreviewed (the ultrareview ran against the prior commit).
**Still true as of v1.5.1** — the mechanism is intact in `main`, touched since
only by #138's 20-line entity-collision fix. Closing it needs `/code-review ultra`
over `1a32f08..707d9b6`, which is user-triggered.
- No human screen-reader pass on the person picker → consolidated into
`todos/pending/2026-08-10-person-picker-screen-reader-pass.md`
- ~~21-05 Task 5 (human browser verification) was never performed~~ — **STRUCK
2026-08-10 as superseded** by Phase 25's human pass; the residue merged into the
todo above

### Release Checklist (v1.4.0)

Expand Down Expand Up @@ -404,6 +442,14 @@ Recent decisions affecting current work:
and arbitrary SVG upload, which is a security feature wearing a UI feature's
clothes and wants its own pass. `todos/pending/2026-08-09-icon-picker-remaining-scope.md`

- **Human screen-reader pass on the person picker** — consolidates the two
surviving v1.5.0 caveats into one task (21-05 Task 5 is struck as superseded by
Phase 25's human pass). axe is clean and still passing, which is not the same
claim: it cannot judge announcement sequence, live-region timing, or whether four
similarly-named groups are distinguishable by ear. Phase 25's M2 change made a
previously-skipped control focusable in that popover *after* the axe scan, so the
gap widened slightly. One person, one sitting, VoiceOver or NVDA actually running.
`todos/pending/2026-08-10-person-picker-screen-reader-pass.md`
- **The release→deploy trigger is dead by construction** — `wp-deploy.yml`
declares `release: types: [published]`, a path that has fired **zero times in
six releases**; all six deploys were manual `workflow_dispatch`. Cause confirmed
Expand Down Expand Up @@ -473,10 +519,21 @@ re-opening either question:**
"fold versus width conflict" flagged on 2026-08-09 was mis-framed and is
**withdrawn**: `160px` is just hardcoded in three places.

**Three things carried, not resolved** (also in the v1.5.0 milestone entry):
1. The #128 fixes shipped **unreviewed** — the ultrareview ran against the prior commit.
2. **No human screen-reader pass** on the person picker; axe is clean, which is not the same claim.
3. 21-05 Task 5 (human browser verification) was never performed; the phase was accepted on automated evidence.
**Reviewed 2026-08-10 — three carried items are now TWO, and both are actionable:**
1. **The #128 fixes shipped unreviewed.** Verified still live: `707d9b6` changed
192 lines of `class-config.php` plus the logic modules, and that mechanism is
intact in `main` (touched since only by #138's 20 lines). It is the same
sanitize path in which the ultrareview found four consecutive holes, and it is
the one round no adversarial pass has ever seen. **Close with `/code-review
ultra` over `1a32f08..707d9b6`** — user-triggered and billed, so it needs Dan.
Highest value of the three, and the cheapest.
2. **The screen-reader pass**, now a real todo rather than prose:
`todos/pending/2026-08-10-person-picker-screen-reader-pass.md`. It absorbed
item 3 and slightly widened — Phase 25's M2 change made a previously-skipped
control focusable in that same popover *after* the v1.5.0 axe scan.
3. ~~21-05 Task 5 (human browser verification)~~ — **STRUCK as superseded.** Phase
25 did a genuine human pass (`25-VERIFICATION.md`); it covered the toolbar and
the locked-checkbox row, not the person picker. That residue is item 2.

**Environment gotcha:** another project's wp-env on this machine has claimed
8888/8889 and at times 8899. Check which ports are free before `wp-env start`,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
---
created: 2026-08-10T00:00:00.000Z
title: Human screen-reader pass on the visibility popover and person picker
area: a11y
files:
- assets/maestro.js (buildRoleGroup + the person picker — four similarly-named groups in one dialog)
- tests/e2e/specs/person-picker-a11y.spec.ts (the axe coverage this does NOT replace)
- .planning/phases/25-edit-mode-toolbar-dark-surface-polish/25-VERIFICATION.md (the human pass that closed the other half)
---

## Problem

**Nobody has driven the person picker in a browser with a screen reader on.**

This merges two items that were tracked separately across v1.5.0 and v1.5.1 and
have turned out to be one task. Both were carried as prose in STATE.md rather
than as a todo, which is how they survived two releases without moving.

## What is actually covered, and what is not

**Covered — axe-core.** `person-picker-a11y.spec.ts` scans the popover in BOTH
empty and populated states (the chips, results list and live-region messages only
exist after interaction, so an empty-state scan would miss most of what the
feature renders). Zero violations against wcag2a/2aa/21a/21aa, scoped to the
popover so wp-admin's own pre-existing findings don't train people to ignore the
suite. This still passes.

**Covered — a human in a live editor, for the OTHER half.** Phase 25 was a real
human pass (`25-VERIFICATION.md`, 2026-08-09) and it deliberately records itself
as such because this project has one checkpoint recorded the other way. It
covered the toolbar and the locked-checkbox row. **It did not cover the person
picker or the four-group popover**, and it names no assistive technology.

**Not covered — anything about sequence or sense.** axe catches
machine-detectable violations. It cannot tell you whether the announcements make
sense in order, whether the live-region timing is usable, or whether four
similarly-named groups ("Hide this item from:", "Hide its sub-items from:", and
their two person equivalents) are actually distinguishable by ear. No automated
result should be read as having replaced that.

## Why this got slightly WORSE, not just older

Phase 25's M2 change altered this same popover **after** the v1.5.0 axe scan: the
derived-locked checkbox moved from natively `disabled` to `aria-disabled`, so a
control that screen-reader focus mode used to skip entirely is now reachable and
refuses its own toggle.

That was the right fix — the lock reason was written for assistive technology and
could never be heard while the row was skipped. But it changes tab order and
announcement sequence in exactly the component that has never had a human pass,
and "focusable control that declines to change" is a pattern automated tooling
cannot evaluate for comprehensibility. The axe suite passes over it either way.

## The task

One person, one sitting, roughly twenty minutes, with VoiceOver or NVDA actually
running:

- Open the visibility popover on an item WITH sub-items, so all four groups are
present. Can you tell the four groups apart by ear alone?
- Tab to a derived-locked checkbox. Is the lock reason announced, and does it
arrive as a description after the name rather than tangled into it?
- Try to toggle it. Is the refusal comprehensible, or does it read as broken?
- Use the person search: type, wait for results, pick someone. Is the live-region
announcement timed usefully, or does it fire before or long after the results?
- Add and remove a chip. Is what happened announced?
- Dismiss by clicking outside. Does focus land somewhere sensible (Phase 25's M3
fix should return it to the anchor)?

## Not automatable, and not a code change

The deliverable is a short findings note plus any defects it turns up — not a
patch. If it finds nothing, that is worth recording too: the claim "a human
listened to this" is one this project cannot currently make about its most
complex surface, and making it once is the point.

## Supersedes

- **21-05 Task 5** (human browser verification) — struck as superseded 2026-08-10.
The plan marked it `autonomous: false` and it was never performed; Phase 21 was
accepted on automated evidence, two Codex rounds, and Claude's own browser-driven
round-trip during 21-04. Phase 25 has since done a genuine human pass over part
of the editor. The residue that actually remains is this todo.
- The "screen-reader pass — narrowed, not closed" caveat carried in STATE.md
since 2026-08-09.

Source: consolidated 2026-08-10 while reviewing the three carried v1.5.0 gaps.
Loading