Four cells on the launcher - Work packages, Release ready, On hold, Overdue -
every number from /api/wps/metrics, which T4.1 built. There is deliberately no
cache fallback anywhere in renderPipeline(): a remembered number sitting beside
three live ones is the failure B4 exists to remove, wearing a different hat.
The cells are the four the endpoint already computes and the dashboard already
filters on, so they map 1:1 onto its flags rather than inventing a fifth slice
nothing downstream understands. wp-creation-app.js now names them (DASH_FLAGS)
for the same reason: a cell linking to a filter the board does not recognise is
a dead link that still looks live.
"Links to a filtered view via a shareable URL" needed the filter to BE URL state,
which it was not - the dashboard kept its flag in a variable. So:
- dashToggleFlag pushes ?flag=<f>, and clears it on the way out of the board
- the creator applies ?flag= before its first render, not after (applying it
after paints the whole board and throws it away)
- Back and Forward move through filters like any other state
- work-package-suite-app.js forwards the flag ACROSS the iframe boundary, since
the creator's src carries only the project. B7/T7.1 dissolves that frame and
this hand-off goes with it; it is commented as such.
Zero is a real answer for one slice of a project that has work in it. Four zeros
on a project with none is not a reading, it is a strip that looks broken - that
case gets a sentence and a way into the creator instead. A failed request gets an
explicit error naming the failure, and no cells at all.
html/index.html the strip, its states, PIPE_CELLS
html/wp-creation-app.js flag as URL state; DASH_FLAGS; dashApplyFlag
html/work-package-suite-app.js forward the flag into the frame; clear on exit
tests/pipeline_check.py new - 43 checks
Done when
[x] every number comes from a server endpoint - proved by poisoning localStorage
with 99 fake packages and demanding the strip still read the server's 4
[x] each cell links to a filtered view via a shareable URL - and the probe
FOLLOWS the link and reads the filter inside the frame rather than trusting
that a correct-looking URL was built
[x] a project with zero work packages renders a sensible empty state
[x] the strip announces updates via aria-live (polite - a count is not an
interruption) and reports aria-busy while it is counting
What the probe caught
The link landed on "Complete the SOP Configuration first". Not the strip's
fault: browser_check.py's fixture stores a bare {governance: …} blob as the SOP
data, where production stores {sop, state}. restoreSavedSOP() needs `state` and
bails without it, so sopComplete stays false and the WP tab shows its gate.
pipeline_check seeds the production shape. The underlying wart is real and is
logged rather than fixed - see BL-018.
Verified one at a time
pipeline_check 43/43 new
launcher_check 58/58
stepper_check 70/70
url_state 23/23 the dashboard's new flag state did not disturb it
aggregates 16/16
browser_check 71/71
a11y 22/22
autosave 34/34
f_items F1-F5 FIXED, F6 REPRODUCES (T7.2)
No colour literal added: still 0 across all page sheets and inline blocks. The
four cells are told apart by a label, a sentence and an accent - three channels,
so colour is not carrying it alone (C1).
Raised, not fixed
BL-018 The WP tab's gate is the last localStorage-derived status in the app.
T4.1 moved the launcher's card to the server; the wizard page still
decides gate-or-creator from wp_suite_sop_complete plus a state blob.
pullProject refreshes both on load so a connected user is fine, but the
two answers come from different places and the fallback is silent.
Includes a second, sharper edge: project-data.js:210 writes that flag
for ANY row returned, including one with no `state` to restore - so the
flag is written and never read consistently. T7.1 owns it.
Question for the PR, per CLAUDE.md: the strip counts Overdue against `data.due`,
which is free text today. CR-004/CR-018 restructure location but not dates. If
"overdue" is going to drive anything beyond a launcher tile, that field needs a
type.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
345 lines
21 KiB
Markdown
345 lines
21 KiB
Markdown
# Backlog
|
||
|
||
Anything noticed during implementation that is real but not in the plan goes here instead of
|
||
into the current PR. `CLAUDE.md` requires this: every change traces to an item ID, so
|
||
unplanned work gets logged rather than built.
|
||
|
||
Add an entry, do not fix it inline. This file is reviewed at `T9.7` and feeds the next spec
|
||
revision.
|
||
|
||
## Format
|
||
|
||
```markdown
|
||
### BL-001 — Short title
|
||
|
||
- **Found during:** T3.2
|
||
- **Where:** path/to/file.js:120
|
||
- **What:** one or two sentences on the problem
|
||
- **Why not now:** out of scope for the current wave / needs a product decision / larger than the task
|
||
- **Suggested wave or follow-up:** wave 9 / next revision / needs Nick
|
||
```
|
||
|
||
## Known follow-ups already identified in the spec
|
||
|
||
These are logged from the source documents, not discovered in code. They are real but
|
||
deliberately deferred.
|
||
|
||
### BL-000a — Validated P6 activity lookup
|
||
|
||
- **From:** `CR-001`
|
||
- **What:** `CR-001` accepts free text for the P6 Activity ID. A validated lookup against an imported P6 activity list was identified as the eventual want.
|
||
- **Why not now:** the Micron schedule is actively being reworked, so importing an activity list now would import churn.
|
||
- **Suggested:** next revision, once the schedule stabilizes.
|
||
|
||
### BL-000b — Field-level toggles in General Information
|
||
|
||
- **From:** `CR-006`
|
||
- **What:** `CR-006` toggles whole sections. General Information may need per-field toggles, since projects differ in which identifiers they use.
|
||
- **Why not now:** section-level toggles cover every removal request currently on the list.
|
||
- **Suggested:** next revision, if a second project needs a different field set.
|
||
|
||
### BL-000c — Estimated versus actual hours productivity factor
|
||
|
||
- **From:** `CR-017`
|
||
- **What:** Actual Hours is retained and rolls up. Comparing it against estimated hours would produce a productivity factor, which was the stated reason for wanting the field.
|
||
- **Why not now:** estimated hours capture is not in scope this round.
|
||
- **Suggested:** next revision.
|
||
|
||
### BL-000d — Attachment merge versus list on export
|
||
|
||
- **From:** `CR-008` / `T9.1`
|
||
- **What:** whether the PDF export merges attachments into one package or lists them separately.
|
||
- **Why not now:** product decision, raised in the `T9.1` PR.
|
||
- **Suggested:** needs Nick.
|
||
|
||
## Found during implementation
|
||
|
||
### BL-001 — The creator overflows horizontally at 1440px
|
||
|
||
- **Found during:** T0.2
|
||
- **Where:** `html/wp-creation-index.html` / `html/wp-creation-styles.css`
|
||
- **What:** the creator lays out 1,551px of content inside a 1,440px viewport, so the page
|
||
scrolls sideways at desk width. Measured by `tests/baseline_shots.py`, which compares
|
||
`documentElement.scrollWidth` against `clientWidth` at each capture. `F2` covers narrow
|
||
widths; no item covers this one. The other three overflowing pages (launcher 425px, SOP
|
||
wizard 429px, field view 432px, all at a 390px viewport) are `F2` and are already scheduled.
|
||
- **Why not now:** wave 1 is scoped to `F1`–`F5`, and `T7.1` dissolves this page's iframe and
|
||
rebuilds its layout regardless — fixing it in wave 1 would be thrown away.
|
||
- **Suggested wave or follow-up:** verify it is gone at `T7.1`; if it survives the rebuild,
|
||
it needs its own item in the next revision.
|
||
- **Root cause, found at T1.4 — not fixed, T7.1 owns it.** `wp-creation-styles.css:815` has
|
||
`@media (max-width: 860px) { body { --nav-w: 56px; } }`, which is correct. But
|
||
`wp-creation-app.js:1389` injects `body{--nav-w:288px;}` into a runtime `<style>` with no
|
||
media query. Injected last, same specificity, so it **wins over the media query** and
|
||
`--nav-w` stays 288px at every width. Everything keyed off it then reserves 288px of
|
||
rail that is not there: `.main` padding-left `calc(288px + 28px)`
|
||
(`wp-creation-styles.css:109`), `.ctx-bar` (`:452`), `.release-banner` (`:488`),
|
||
`.section-nav-bar` (`:596`) and `.sticky-save { left: var(--nav-w,288px) }` (`:820`).
|
||
At a 390px screen that forces the initial containing block to 485px.
|
||
The fix is to give the injected rule the same breakpoint, or to stop injecting the
|
||
value that the stylesheet already declares — one line, but it belongs with the creator
|
||
rebuild rather than in a wave 1 rendering task.
|
||
- **Consequence for `F4`:** every `position: fixed; right: 0` element on this page sits at
|
||
the right edge of that 485px box, which is 95px off the visible 390px screen. The
|
||
comments drawer is placed correctly relative to its containing block; the containing
|
||
block is wrong. `T1.4` reports this as an attributed note rather than a drawer defect,
|
||
so nobody is sent to the wrong file.
|
||
- **Update, T1.2:** the 1440px half of this is **resolved as a side effect**, not by intent.
|
||
The unbreakable `#wp-usermenu` run that `T1.2` fixed was the cause of four of the five
|
||
overflows recorded in wave 0 — launcher, SOP wizard and field view at 390px, and the
|
||
creator at 1440px. Capture now reports overflow on 1 of 14 shots instead of 5. What
|
||
remains is the creator at **390px** (485px of content), which is its own layout rather
|
||
than the shared chrome. Left open so `T7.1` still checks it.
|
||
|
||
### BL-002 — `outline: none` appears three times in the wizard sheet, not once
|
||
|
||
- **Found during:** T0.1
|
||
- **Where:** `html/work-package-suite-styles.css:325`, `:347`, `:501`
|
||
- **What:** `A3`/`F5` cite the focus-ring removal at `322-328` only. The same
|
||
`outline:none` + pale 3px glow is repeated at `:347` (`.user-pick:focus`), and `:501`
|
||
(`.seq-step input.seq-label:focus`) removes the outline with **no** replacement at all,
|
||
which is a straight CLAUDE.md violation.
|
||
- **Why not now:** it is in scope for `T3.4`, not a separate item — recorded so the task
|
||
fixes all three rather than the one the review cited.
|
||
- **Suggested wave or follow-up:** fold into `T3.4`.
|
||
|
||
### BL-003 — User-menu links are 16px tap targets
|
||
|
||
- **Found during:** T1.2
|
||
- **Where:** `html/auth-guard.js:186-191` (`buildUserMenu`'s `link()`)
|
||
- **What:** every link in the app bar's user menu — including `Sign out` — renders 16px
|
||
tall, from `font:400 13px/1.2`. `T1.2` made them all reachable at 390px, but reachable is
|
||
not the same as comfortably tappable on the gloved-hands surface. Well under the usual
|
||
24–44px guidance.
|
||
- **Why not now:** `T1.2` is explicitly triage and `T2.2` replaces this markup with the
|
||
drawer, which has its own tap targets. Enlarging them here would change the 1440px layout
|
||
the task must leave byte-identical, and would be thrown away in wave 2.
|
||
- **Suggested wave or follow-up:** `T2.2` should ship the drawer with adequate targets;
|
||
`C1`'s audit at `T9.5` confirms it app-wide.
|
||
|
||
### BL-004 — `help.js` ships a 52-colour palette in a different design language
|
||
|
||
- **Found during:** T3.1
|
||
- **Where:** `html/help.js:79` (the injected `<style>`)
|
||
- **What:** the help centre injects its own stylesheet with **52 colour literals and zero
|
||
`var()`**. It is not a fourth copy of the suite palette — it is a different one: slate
|
||
(`#27313f`, `#334155`, `#e2e8f0`), violet (`#7c3aed`, `#f3e8ff`), its own blue
|
||
(`rgba(37,99,214,.15)`, see BL-008) and its own greys (`#fafbfc`, `#eef1f6`, `#f4f6f9`,
|
||
`#f7f8fa`). It loads on the launcher, SOP wizard, creator and field view.
|
||
- **Why not now:** `T3.2`'s contract is "no rendered change", and converting this palette is a
|
||
restyle, not a consolidation — it would change the help centre on four pages and break the
|
||
empty-screenshot-diff done-when. The token rule in `CLAUDE.md` does reach it, so it is real
|
||
work, not a non-issue.
|
||
- **Suggested wave or follow-up:** wave 9, alongside `C4`. Documented in
|
||
`docs/reference/tokens.md` §1.
|
||
|
||
### BL-005 — Two modals are styled entirely by inline `style=` attributes
|
||
|
||
- **Found during:** T3.1
|
||
- **Where:** `html/auth-guard.js:67-92` (change-password) and `html/wp-format.js:120-150`
|
||
(preferences)
|
||
- **What:** 35 raw colour literals between them — `#0f62fe`, `#8d8d8d`, `#e0e0e0`, `#defbe6`,
|
||
`#fff1f1`, `#0e6027`, `rgba(20,30,50,.5)` and so on — written into `style=` strings, so no
|
||
stylesheet can reach them and no token can either.
|
||
- **Why not now:** they are markup built by JS, not a stylesheet, so they are outside `T3.2`'s
|
||
four-sheet surface. Both dialogs are rebuilt as accessible components under `C1`.
|
||
- **Suggested wave or follow-up:** `T9.5`, with the `C1` audit.
|
||
|
||
### BL-006 — Seventeen half-pixel font sizes
|
||
|
||
- **Found during:** T3.1
|
||
- **Where:** `html/wp-creation-styles.css` (14) and `html/wp-chrome.css` (3)
|
||
- **What:** `9.5px`, `10.5px`, `11.5px`, `12.5px`, `13.5px` sit inside an otherwise integer
|
||
type scale of 27 distinct sizes. They round inconsistently between engines and there is no
|
||
reason for any of them.
|
||
- **Why not now:** retiring them moves text on every creator screen; `T3.2` forbids rendered
|
||
change and `T7.1` re-lays-out this page anyway.
|
||
- **Suggested wave or follow-up:** `T7.1`. See `docs/reference/tokens.md` §6a.
|
||
|
||
### BL-007 — `--radius: 0` is contradicted 45 times in the sheet that declares it
|
||
|
||
- **Found during:** T3.1
|
||
- **Where:** `html/wp-creation-styles.css:26` and 45 raw `border-radius` values in the same file
|
||
- **What:** the creator declares `--radius: 0` and honours it 23 times, then writes `2px 3px
|
||
4px 5px 6px 8px 9px 10px 12px 14px 20px 50%` directly in 45 other places, plus two
|
||
asymmetric CTA radii at `:707` and `:716`. Square corners are the Carbon idiom and the
|
||
intent everywhere else in the suite; this one sheet drifted.
|
||
- **Why not now:** changing 45 radii is the most visible diff available, and `T3.2` must
|
||
produce none.
|
||
- **Suggested wave or follow-up:** `T7.1`. See `docs/reference/tokens.md` §6c.
|
||
|
||
### BL-008 — There is a second brand blue: `#2563d6`
|
||
|
||
- **Found during:** T3.1
|
||
- **Where:** `html/wp-creation-styles.css:565`, `html/help.js`, `html/wp-creation-app.js:1257`
|
||
- **What:** `.sop-inherited` — the highlight on every field a work package inherited from its
|
||
SOP — fills with `rgba(37,99,214,0.07)`, which is **`#2563d6`**, not the suite's `#0f62fe`.
|
||
`help.js` carries the same blue at `.15` alpha and the print window uses it solid for
|
||
headings. At 7% nobody has noticed, but "one accent colour" is not currently true even after
|
||
the four token systems collapse to one.
|
||
- **Why not now:** swapping it changes a rendered fill, which `T3.2` forbids. It is the same
|
||
conversation as the green action buttons.
|
||
- **Suggested wave or follow-up:** wave 9, with `C4`. `T3.5` is scoped to buttons; this is a field fill. See `docs/reference/tokens.md` §8-E.
|
||
|
||
### BL-009 — A ninth amber, four points from the eighth
|
||
|
||
- **Found during:** T3.2
|
||
- **Where:** `html/field.html:35` (`.pill.warn`)
|
||
- **What:** the field view's warn pill uses `#8a6d00`; every other warning text in the app is
|
||
`#8e6a00`. Four points apart, doing the same job, on the surface that is read through a
|
||
face shield. Almost certainly a typo rather than a decision — `field.html`'s inline `<style>`
|
||
was missed by the `T3.1` inventory, which is why it survived this long.
|
||
- **Why not now:** merging it moves a rendered colour, which `T3.2` forbids. `T3.2` named it
|
||
`--wp-status-warning-text-alt` so it is visible rather than hidden in a hex.
|
||
- **Suggested wave or follow-up:** wave 9, with `C4`. `T3.5` is scoped to buttons; this is a status pill. See `docs/reference/tokens.md` §8-K.
|
||
|
||
### BL-010 — 829 raw spacing, type and radius values remain inside rules
|
||
|
||
- **Found during:** T3.2
|
||
- **Where:** all five page stylesheets; 492 of them in `html/wp-creation-styles.css`
|
||
- **What:** `T3.2` removed every raw **colour** from the page sheets, but 483 spacing values,
|
||
281 font-sizes and 65 radii are still written literally in rules. The token *declarations*
|
||
are aliased — `--s1`…`--s6`, `--ctl`, `--radius`, `--mono`, `--sans` all resolve from
|
||
`theme-light.css` — but the rules that should consume them do not.
|
||
- **Why not now:** not effort — arithmetic. The creator's spacing is every integer from 1px to
|
||
14px, which is a histogram rather than a scale, so there is no token `padding: 9px 11px` maps
|
||
to without changing one of the two numbers. `T3.2` forbids changing a rendered value, so
|
||
tokenising these and honouring that constraint are mutually exclusive. This is the one `T3.2`
|
||
done-when not met, and it is recorded as not met rather than quietly skipped.
|
||
- **Suggested wave or follow-up:** `T5.x` and `T7.1`, where these pages are re-laid-out and the
|
||
values are being chosen again anyway. See `docs/reference/tokens.md` §6b and §11.
|
||
|
||
### BL-011 — Three JS-injected overlays race to append on the SOP page
|
||
|
||
- **Found during:** T3.2
|
||
- **Where:** `html/work-package-suite.html` — `#wp-sync-badge`, `.wp-navscrim`, `#wp-sidenav`
|
||
- **What:** the sync badge, the drawer scrim and the drawer are appended to `<body>` by three
|
||
different scripts after async work, so their DOM order varies run to run. Nothing is painted
|
||
differently — all three are `position: fixed` with their own `z-index` — but any test that
|
||
keys elements by sibling index sees dozens of phantom differences on this page. It cost real
|
||
time in `T3.2` before the cause was found, and `tests/token_check.py` now keys by identity
|
||
to avoid it.
|
||
- **Why not now:** invisible to users, and the fix is ordering in three separate scripts, which
|
||
is a change with no observable benefit while `T7.1` is still going to move this code.
|
||
- **Suggested wave or follow-up:** wave 9, if it is still true after `T7.1`.
|
||
|
||
### BL-012 — `admin.html` and the creator at 1440px are not stable enough to screenshot-diff
|
||
|
||
- **Found during:** T3.2
|
||
- **Where:** `tests/baseline_shots.py` output for `admin-390`, `admin-1440`, `creator-1440`
|
||
- **What:** the task brief's trap 2 says `admin.html` and `users.html` are not byte-stable.
|
||
Measured by capturing wave 2 against itself: **`users` is stable at both widths**, and the
|
||
unstable third is the **creator at 1440px** (344,272 px differ, bbox 288,14→1439,4924).
|
||
`admin` is worse than "live timestamps" suggests — its captured page *height* varies by about
|
||
600px between runs, so the two images cannot even be compared pixel-for-pixel.
|
||
- **Why not now:** the screenshots are a review aid, not a gate; `tests/token_check.py` now
|
||
covers what the diff was being asked to prove, and covers it better.
|
||
- **Suggested wave or follow-up:** wave 9, alongside `C2`. Either freeze the clock in the
|
||
fixture or exclude the live regions from capture — otherwise every later wave re-learns this.
|
||
|
||
### BL-013 — The creator's inputs have no visible focus ring at all
|
||
|
||
- **Found during:** T3.4
|
||
- **Where:** `html/wp-creation-styles.css:168` (`outline: none` on every input, textarea and
|
||
select) and `:171` (`:focus` replaces it with `box-shadow: 0 0 0 3px var(--accent-dim)`)
|
||
- **What:** the same defect `BL-002` recorded in the wizard sheet, in the sheet next door.
|
||
Measured in the browser with focus emulation on: a focused creator input reports
|
||
`outline-style: none`, and its only focus cue is a 3px `#edf5ff` glow against a `#ffffff`
|
||
field — a 1.05:1 edge. `.wp-nav-search:focus` (`:765`) is the same. That is `CLAUDE.md`'s
|
||
"outline: none without a replacement of at least equal visibility", on the page with the
|
||
most form controls in the app.
|
||
- **Why not now:** `T3.4`'s files are the SOP wizard stylesheet, and `BL-002` scoped the
|
||
three sites it folded in to that sheet. The creator is rebuilt at `T7.1`/`T7.2`.
|
||
- **Suggested wave or follow-up:** `T7.2`, or `T9.5` with the `C1` audit if it survives the
|
||
rebuild. The fix is the ring `T3.4` established: `outline: 2px solid var(--cds-focus);
|
||
outline-offset: -2px`, which `console.css`, `wp-chrome.css` and now the wizard all use.
|
||
|
||
### BL-015 — The creator's stepper tabs are still forced uppercase
|
||
|
||
- **Found during:** T3.5
|
||
- **Where:** `html/wp-creation-styles.css:105` (`.step-tab`)
|
||
- **What:** `A5` scopes sentence case to buttons and field labels, and `T3.5` removed the
|
||
forced uppercase from both. `.step-tab` is neither — it is a stepper tab — so it was left,
|
||
and it is now the only uppercase interactive text on the page.
|
||
- **Why not now:** out of `A5`'s stated scope, and `A4`/`S9` rebuild the stepper.
|
||
- **Suggested wave or follow-up:** `T7.x`, with the stepper rebuild.
|
||
|
||
### BL-016 — Back to a URL with no `step` leaves the wizard on the step it was on
|
||
|
||
- **Found during:** T5.1
|
||
- **Where:** `html/work-package-suite-app.js`, the `WPUrl.onChange` handler
|
||
- **What:** the popstate handler reads `parseInt(state.step, 10)` and acts only when
|
||
the result is `>= 1`. Going from `?project=X&step=6` back to `?project=X` yields
|
||
`NaN`, so nothing happens and the wizard stays on step 6 while the address bar says
|
||
step 1. `T4.2`'s own probe never caught it because it moves between two URLs that
|
||
both carry a `step`, so the NaN branch was never taken. The fix is one expression —
|
||
treat a missing `step` as 1 — but it is `S3`'s code and `T4.2`'s done-whens, not
|
||
`A4`'s.
|
||
- **Why not now:** `CLAUDE.md` — do not fix what you notice in passing. `T5.1`'s rail
|
||
makes it easier to reach (ten keyboard-reachable buttons instead of ten chips) but
|
||
does not cause it, and folding an `S3` correction into an `A4` diff makes both
|
||
unreviewable.
|
||
- **Suggested wave or follow-up:** wave 9, with `C2`. `tests/stepper_check.py` pins the
|
||
current behaviour with a named check so the fix has a test waiting for it.
|
||
|
||
### BL-017 — The native-dialog baseline metric counts prose
|
||
|
||
- **Found during:** T5.1
|
||
- **Where:** `docs/reference/file-map.md` §4, metric 1
|
||
- **What:** the metric is `grep -ohE '\b(alert|confirm|prompt)\(' *.js *.html`, which
|
||
matches those words inside comments as readily as inside code. Four comments written
|
||
during `T5.1` — every one of them *about* removing a dialog — pushed the count from
|
||
80 to 82 while the task was deleting two real calls. They were reworded, but the next
|
||
person to explain a dialog in a comment will move the number again, and `T5.8` and
|
||
wave 9 both have to drive it to a target.
|
||
- **Why not now:** redefining a wave 0 baseline mid-plan is worse than the noise; the
|
||
count is comparable to itself as long as everyone measures it the same way.
|
||
- **Suggested wave or follow-up:** `T5.8`, which owns the wizard's count, should record
|
||
a comment-stripped figure alongside the raw one and state both. Wave 9 sets the
|
||
target against the stripped figure.
|
||
|
||
### BL-018 — The Work Package tab's gate is the last localStorage-derived status
|
||
|
||
- **Found during:** T5.3
|
||
- **Where:** `html/work-package-suite-app.js` — `restoreSavedSOP()` sets `sopComplete`,
|
||
`renderWPTab()` shows the gate or the creator on it
|
||
- **What:** `T4.1` moved the *launcher's* SOP status onto `/api/projects/{id}/summary`, and
|
||
`aggregates_check.py` proves the card reports the server's answer over a lying cache. The
|
||
SOP **wizard page** still decides whether to show the creator or the "complete the SOP
|
||
Configuration first" gate from `localStorage.wp_suite_sop_complete` plus a `wp_suite_state`
|
||
blob. `ProjectData.pullProject()` refreshes both from the server on load, so a signed-in
|
||
user with a working connection is fine — but the two answers come from different places,
|
||
and the fallback is silent rather than an error state, which is the shape `B4` objects to.
|
||
- **Also:** `project-data.js:210` writes `wp_suite_sop_complete = '1'` whenever
|
||
`/api/sops/latest` returns any row, including one whose `data` carries no `state`. The
|
||
wizard then holds a browser that believes the SOP is complete and has nothing to restore,
|
||
so `restoreSavedSOP()` bails and `sopComplete` stays false — the flag is written and never
|
||
read consistently. Found because `browser_check.py`'s fixture seeds exactly that shape, and
|
||
a pipeline-strip link consequently landed on the gate. `pipeline_check.py` seeds the
|
||
production shape (`{sop, state}`) instead.
|
||
- **Why not now:** `T5.3` is the strip. Changing which source the WP gate trusts changes what
|
||
the SOP wizard does when offline, and `B7`/`T7.1` dissolves that iframe and rewrites this
|
||
hand-off wholesale.
|
||
- **Suggested wave or follow-up:** `T7.1`, or wave 9 with `C2` if the gate survives the
|
||
rebuild unchanged. Either way `browser_check.py`'s fixture should adopt the `{sop, state}`
|
||
shape so it stops being the only place this discrepancy is visible.
|
||
|
||
### BL-014 — Four controls fall back to the browser's default focus ring
|
||
|
||
- **Found during:** T3.4
|
||
- **Where:** `html/index.html` `.proj-row select`, `.proj-form-grid input`, `.link-like`;
|
||
`html/field.html` `.fld-search`
|
||
- **What:** these have no focus rule, so they get the UA default (`1px auto #111`). Visible,
|
||
so not a `C1` violation — but it is a fourth focus idiom beside the app's 2px `--cds-focus`
|
||
inset ring, and it does not follow the accent if the accent ever changes.
|
||
- **Why not now:** adding rings to the launcher and field view is outside `T3.4`, whose files
|
||
are the wizard stylesheet, and both surfaces are touched by later waves anyway.
|
||
- **Suggested wave or follow-up:** `T9.5`, with the `C1` audit.
|
||
- **Update, T5.2 — two of the four sites no longer exist.** `.proj-row select` and
|
||
`.link-like` went with the project-picker card (`B3`). The third, `.proj-form-grid input`,
|
||
survives in the rebuilt create form and was **measured rather than assumed**: with CDP
|
||
focus emulation on it draws `2px var(--cds-focus)` from the app-wide `:where()` floor
|
||
`T4.7` added, which post-dates this entry. So the launcher half of BL-014 is closed;
|
||
what is left is `field.html`'s `.fld-search`, and `T9.5` should re-measure that one the
|
||
same way rather than inheriting this entry's wording.
|