T0.1 - build the file map and verify the plan's line references
Wave 0 exists because the plan's line numbers came from a review of users/directory-super-user rather than a fresh read. This is the fresh read: 7 pages, 6 stylesheets, 11,867 lines, with each page's stylesheets, scripts and iframe role recorded, and all seven baseline counts captured with the command that produced them. Four discrepancies, one of which matters a great deal: D2 - CLAUDE.md's "logged-override path for predecessors stays (A1). See wp-creation-app.js:1962-1972" cites the wrong function. That range is dashIssue(), which REFUSES to issue and says "open the package to release it early with a logged reason". The reviewer read that sentence and correctly inferred an override exists, but cited the mention rather than the code. The audited path is confirmEarlyRelease() at 967-984 plus seven satellites (state at 392, call sites at 998 and 1149, persisted at 1117, rendered at 1215, rehydrated at 1674, reset at 481/488/1744). A T7.3 that preserved only 1962-1972 would delete the business rule while believing it had protected it. D1 - "6 pages, 4 stylesheets" is 7 and 6; wave-0's own parenthetical lists seven names. Every "all 6 pages" done-when is off by one. D3 - four documents the plan reads from are deliverables not yet written. D4 - the creator overflows horizontally at 1440px, which no F item covers. Logged as BL-001 rather than fixed, since T7.1 rebuilds that layout anyway. BL-002 records that outline:none appears three times in the wizard sheet, not once, so T3.4 fixes all three. Counts confirmed against the review: 79 dialogs (43 in the creator), 12 div and 2 span onclick, 15 help-tip badges, 0 aria-live, 0 pushState. The "4 declarations of #0f62fe" needed a definition - there are 31 occurrences and 14 custom-property declarations; the 4 is the number of stylesheets declaring their own accent token, which is the number wave 9 should drive to 1. No application code changed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
303
docs/reference/file-map.md
Normal file
303
docs/reference/file-map.md
Normal file
@@ -0,0 +1,303 @@
|
||||
# File map — `html/` and the references the plan depends on
|
||||
|
||||
**Task:** `T0.1` · **Produced:** August 14, 2026 · **Branch:** `feat/wp-suite-r2-implementation`
|
||||
|
||||
Wave 0 exists because the item IDs and line numbers in this plan came from a UX review of
|
||||
branch `users/directory-super-user`, not from a fresh read. This document is the fresh read.
|
||||
Everything below was verified against the working tree, not quoted from the review.
|
||||
|
||||
**Read the [Discrepancies](#discrepancies) section before starting any wave.** Four things the
|
||||
plan asserts are wrong, and one of them (`A1`) guards a code path CLAUDE.md says must not change.
|
||||
|
||||
---
|
||||
|
||||
## 1. Pages
|
||||
|
||||
`html/` holds **7 pages, 6 stylesheets, 11,867 lines**. The plan says "6 pages, 4 stylesheets,
|
||||
roughly 11,900 lines" — the line count is right, the other two are not. See D1.
|
||||
|
||||
| Page | Called in this plan | Lines | Stylesheets (load order) | Scripts (load order) | Iframe |
|
||||
|---|---|---|---|---|---|
|
||||
| `html/login.html` | login | 163 | `theme-light.css` | `login.js` | neither |
|
||||
| `html/index.html` | launcher | 703 | `theme-light.css`, `wp-chrome.css` | `auth-guard`, `wp-format`, `feedback-config`, `project-data`, `help`, *(inline 418–700)*, `wp-chrome` | neither |
|
||||
| `html/work-package-suite.html` | SOP wizard | 437 | `theme-light.css`, `wp-chrome.css`, `work-package-suite-styles.css` | `auth-guard`, `wp-format`, `feedback-config`, `project-data`, `help`, `work-package-suite-app`, `wp-chrome` | **hosts** |
|
||||
| `html/wp-creation-index.html` | creator | 401 | `theme-light.css`, `wp-creation-styles.css` | `auth-guard`, `wp-format`, `feedback-config`, `project-data`, `help`, `wp-creation-app` | **child** |
|
||||
| `html/admin.html` | admin | 219 | `theme-light.css`, `wp-chrome.css`, `console.css`, `wp-sidenav.css` | `auth-guard`, `wp-format`, `console-util`, `admin`, `wp-chrome`, `wp-sidenav` | neither |
|
||||
| `html/users.html` | directory/users | 106 | `theme-light.css`, `wp-chrome.css`, `console.css`, `wp-sidenav.css` | `auth-guard`, `wp-format`, `console-util`, `users`, `wp-chrome`, `wp-sidenav` | neither |
|
||||
| `html/field.html` | field view | 93 | `theme-light.css`, `wp-chrome.css`, `wp-sidenav.css` | `auth-guard`, `wp-format`, `project-data`, `help`, `field`, `wp-chrome`, `wp-sidenav` | neither |
|
||||
|
||||
No script anywhere in `html/` uses `defer`, `async`, or `type="module"`. Every one is a
|
||||
render-blocking classic script. `auth-guard.js` and `wp-format.js` load in `<head>`; the rest
|
||||
load at the end of `<body>`.
|
||||
|
||||
### The iframe boundary (matters for `B7` / `T7.1`)
|
||||
|
||||
`work-package-suite.html:383` declares `<iframe id="wp-frame">` with **no `src`**.
|
||||
`work-package-suite-app.js:581` sets it at runtime to
|
||||
`wp-creation-index.html?embedded=1&project=<id>`.
|
||||
|
||||
The creator is the only page that loads **neither `wp-chrome.css` nor `wp-chrome.js`** — that is
|
||||
why it has no app bar of its own and why it looks like part of the wizard. `T7.1` has to give it
|
||||
that chrome back, or deliberately not.
|
||||
|
||||
Three scripts branch on `window.top !== window.self` and will change behaviour when the frame
|
||||
goes away:
|
||||
|
||||
| Script | Line | Framed behaviour |
|
||||
|---|---|---|
|
||||
| `auth-guard.js` | 15 | redirects `window.top` to `login.html` |
|
||||
| `wp-chrome.js` | 17 | returns early, renders no chrome |
|
||||
| `help.js` | — | suppresses the Help FAB in the child |
|
||||
|
||||
### Pages that are not what the plan implies
|
||||
|
||||
- **`field.html` is 93 lines.** It is a shell; `field.js` (178 lines) builds it. A task that says
|
||||
"edit the field view page" almost always means `field.js`.
|
||||
- **`index.html` carries ~296 lines of inline `<style>`** (lines 16–312) — the bulk of the
|
||||
launcher's CSS is not in any stylesheet. `T3.x` token work has to reach inside it.
|
||||
- **`admin.html` and `users.html` are near-identical shells** over `console.css` + `console-util.js`.
|
||||
|
||||
---
|
||||
|
||||
## 2. Stylesheets
|
||||
|
||||
| File | Lines | Purpose | Consumed by |
|
||||
|---|---|---|---|
|
||||
| `theme-light.css` | 249 | Carbon light (g10) token set, base type, shared dark appbar | **all 7 pages** (always first) |
|
||||
| `console.css` | 191 | dense admin tables and toolbars | admin, users |
|
||||
| `work-package-suite-styles.css` | 610 | SOP wizard page sheet | SOP wizard |
|
||||
| `wp-chrome.css` | 237 | injected chrome: project switcher, global search | launcher, SOP wizard, admin, users, field |
|
||||
| `wp-creation-styles.css` | 884 | creator page sheet | creator |
|
||||
| `wp-sidenav.css` | 90 | off-canvas nav drawer | admin, users, field |
|
||||
|
||||
**No `@import` exists in any stylesheet.** Composition is entirely `<link>` order.
|
||||
`theme-light.css` is linked first on all 7 pages.
|
||||
|
||||
### The four parallel token systems (`S5`, consolidated in wave 3)
|
||||
|
||||
| Sheet | Prefix | Root tokens |
|
||||
|---|---|---|
|
||||
| `theme-light.css` | `--cds-*` (2–117) and `--wp-appbar-*` (169–176) | 114 + 6 |
|
||||
| `console.css` | **unprefixed** (12–20) | 28 |
|
||||
| `work-package-suite-styles.css` | **unprefixed** (1–18) | 16 |
|
||||
| `wp-creation-styles.css` | **unprefixed** (9–31) | 21 |
|
||||
| `wp-chrome.css` | `--wpc-*`, scoped to `.wp-chrome`, **not `:root`** (18–36) | 0 at root |
|
||||
| `wp-sidenav.css` | none — every colour is a hardcoded hex | 0 |
|
||||
|
||||
The three unprefixed sheets are the collision risk. They are **mutually exclusive per page**
|
||||
today (console on admin+users, wizard sheet on the wizard, creator sheet on the creator), so
|
||||
nothing currently breaks — wave 3 must not assume that stays true once chrome is unified.
|
||||
|
||||
Redeclared across sheets with the **same** value: `--bg`, `--border`, `--border-strong`,
|
||||
`--text`, `--accent`, `--red`, `--shadow`, `--text-dim`.
|
||||
Redeclared with **different** values — these are the real defects:
|
||||
|
||||
- `--shadow-lg` — `0 4px 16px rgba(0,0,0,0.16)` (wizard) vs a different blur in the creator
|
||||
- `--mono` — `console.css` drops `ui-monospace` and `Segoe UI Mono` from the stack
|
||||
- `--surface` — `#fff` (console) vs `#ffffff` (creator); same colour, two notations
|
||||
- `--appbar: #161616` (wizard) duplicates `--wp-appbar-bg: #161616` (theme) under another name
|
||||
|
||||
Set at runtime on `documentElement`, declared in no stylesheet:
|
||||
`--wp-chrome-h` (`work-package-suite-app.js:528`), `--rail-top` (`wp-creation-app.js`).
|
||||
Declared on `body` rather than `:root`: `--nav-w` (`wp-creation-styles.css:673,674,805`).
|
||||
|
||||
Only cross-file dependency: `work-package-suite-styles.css` consumes `--cds-hover-primary`,
|
||||
which only `theme-light.css` declares.
|
||||
|
||||
---
|
||||
|
||||
## 3. Verified references
|
||||
|
||||
Every reference the plan relies on, checked against the working tree.
|
||||
|
||||
| Reference | Claim | Status | Actually |
|
||||
|---|---|---|---|
|
||||
| `wp-creation-app.js:1144` | `alert()` "Subject and WP Type are required" | **CONFIRMED** | exact |
|
||||
| `wp-creation-app.js:1962-1972` | logged-override path for predecessors | **MOVED — see D2** | that range is `dashIssue()`, which *refuses*. Real path: **`967–984`** |
|
||||
| `work-package-suite-app.js:326` | only `beforeunload`, analytics dwell | **CONFIRMED** | exact; sole `beforeunload` in all of `html/` |
|
||||
| `work-package-suite-styles.css:322-328` | `outline:none` + pale 3px glow | **CONFIRMED** | block runs 321–328, `outline:none` on 325 |
|
||||
| `work-package-suite-styles.css:336` | comment about `.field-hint` unstyled | **CONFIRMED** | comment 336–338, rule on 339 |
|
||||
| `console.css:85-87` | contrast fix not propagated | **CONFIRMED** | comment 85–87, fix on 88 |
|
||||
| `admin.js:484-517` | language and time localization | **CONFIRMED** | exact — "Localization defaults" block |
|
||||
| `server/seed_demo.py` | seeds without authenticating | **CONFIRMED** | zero auth code in 178 lines |
|
||||
|
||||
Notes that change what a later task should do:
|
||||
|
||||
- **`work-package-suite-styles.css`** — `outline: none` appears **three** times, not once: 325
|
||||
(the cited block), 347 (`.user-pick:focus`, same pale glow), and 501
|
||||
(`.seq-step input.seq-label:focus`, *no* replacement glow at all). `A3`/`F5` should fix all three.
|
||||
- **`console.css:85-87`** — the comment measures `#8d8d8d` on white at **3.3:1**. Wave 4's `T4.6`
|
||||
says "about 2.9:1". They disagree; `T4.6` should re-measure rather than quote either. Both
|
||||
other sheets still bind helper text to the rejected `#8d8d8d`
|
||||
(`work-package-suite-styles.css:10`, `wp-creation-styles.css:17`), and the creator applies it
|
||||
at **10px** (`wp-creation-styles.css:374`), worse than the 12px the comment measures.
|
||||
- **`seed_demo.py`** fails *loudly but confusingly*: `call()` swallows the `HTTPError` and returns
|
||||
the error body, so line 101's `proj["id"]` raises `KeyError` instead of reporting a 401.
|
||||
Only `/api/health` is unauthenticated, so the health check passes and it dies immediately after.
|
||||
|
||||
---
|
||||
|
||||
## 4. Baseline counts
|
||||
|
||||
Recorded so wave 9 can prove they went down. Run from `html/` unless stated.
|
||||
|
||||
| # | Metric | Review | Actual | Command |
|
||||
|---|---|---|---|---|
|
||||
| 1 | native dialogs app-wide | 79 | **79** ✓ | `grep -ohE '\b(alert\|confirm\|prompt)\(' *.js *.html \| wc -l` |
|
||||
| 2 | …of those, in the creator | 43 | **43** ✓ | same, over `wp-creation-app.js` |
|
||||
| 3 | `<div onclick>` | 12 | **12** ✓ | `grep -oE '<div[^>]*onclick' *.html *.js \| wc -l` |
|
||||
| 4 | `<span onclick>` | 2 | **2** ✓ | `grep -oE '<span[^>]*onclick' *.html *.js \| wc -l` |
|
||||
| 5 | `#0f62fe` accent systems | 4 | **4** ✓ | see below |
|
||||
| 6 | `.help-tip` badges | 15 | **15** ✓ | `grep -oE 'class="help-tip"' *.html \| wc -l` |
|
||||
| 7 | `aria-live` regions | 0 | **0** ✓ | `grep -ohE 'aria-live' *.html *.js \| wc -l` |
|
||||
| 8 | `pushState` calls | 0 | **0** ✓ | `grep -ohE 'pushState' *.html *.js \| wc -l` |
|
||||
|
||||
Dialogs by file: `wp-creation-app.js` 43 · `work-package-suite-app.js` 14 · `users.js` 10 ·
|
||||
`admin.js` 6 · `index.html` 6.
|
||||
`<div onclick>` by file: `work-package-suite.html` 10 · `wp-creation-index.html` 1 ·
|
||||
`work-package-suite-app.js` 1. Both `<span onclick>` are in `wp-creation-app.js`.
|
||||
|
||||
**Metric 5 needs its definition stated**, or wave 9 will measure a different thing.
|
||||
`#0f62fe` appears **31** times across `html/`, and **14** of those are custom-property
|
||||
declarations. The review's "4" is the number of **stylesheets that declare their own accent
|
||||
token** — the four parallel systems:
|
||||
|
||||
```
|
||||
grep -nE '^\s*--[a-zA-Z0-9-]+\s*:\s*#0f62fe' *.css # 14 declarations, in 4 sheets
|
||||
```
|
||||
|
||||
| Sheet | Token |
|
||||
|---|---|
|
||||
| `theme-light.css` | `--cds-interactive-01` (+ 6 Carbon aliases) |
|
||||
| `work-package-suite-styles.css:2` | `--primary` |
|
||||
| `wp-chrome.css:25` | `--wpc-accent` |
|
||||
| `wp-creation-styles.css:18` | `--accent` |
|
||||
|
||||
**The wave 9 target is 1.** Track the sheet count, not the raw occurrence count.
|
||||
|
||||
**Metric 6:** 15 in page markup (`work-package-suite.html` 3, `wp-creation-index.html` 12).
|
||||
A 16th lives in `help.js:261` inside the help centre's own copy, demonstrating the component —
|
||||
it is not a page badge. None carries `tabindex`, and `help.js:26` styles only `:hover`/`:focus`,
|
||||
so a `<span>` with no tabindex is **keyboard-unreachable**. That is the `C1` defect, and it
|
||||
confirms "unreachable" literally.
|
||||
|
||||
**Metric 7:** `login.html:99-100` uses `role="alert"` and `role="status"`, which are implicit
|
||||
live regions. The count of the literal `aria-live` attribute is 0, matching the review. CLAUDE.md
|
||||
points at these two lines as the pattern to copy — they are real and correct.
|
||||
|
||||
**Metric 8:** `pushState` is 0. There is **one** `history.replaceState` at `login.js:196`,
|
||||
cleaning the URL after sign-in. It is not routing, so `X1`'s premise holds: no work package has
|
||||
an addressable URL.
|
||||
|
||||
---
|
||||
|
||||
## 5. Running it
|
||||
|
||||
```bash
|
||||
uvicorn server.app:app # against a throwaway SQLite database
|
||||
python server/smoketest.py # API; signs in
|
||||
python tests/browser_check.py # pages boot, self-contained
|
||||
python tests/baseline_shots.py # screenshots, self-contained
|
||||
```
|
||||
|
||||
`tests/browser_check.py` and `tests/baseline_shots.py` are self-contained: each creates a
|
||||
throwaway SQLite database, seeds a fixture, starts its own uvicorn on a free port, drives
|
||||
headless Edge or Chrome over CDP, and tears everything down. **Your real `wpsuite.db` is never
|
||||
touched.** Both need Edge or Chrome on the machine; set `WP_BROWSER` to override discovery.
|
||||
|
||||
Screenshots for a before/after pair:
|
||||
|
||||
```bash
|
||||
python tests/baseline_shots.py --out docs/reference/baseline # before (committed)
|
||||
python tests/baseline_shots.py --out /tmp/after --label after # after
|
||||
python tests/baseline_shots.py --pages creator --widths 390,768,1024,1440
|
||||
```
|
||||
|
||||
`tests/` is referenced by **no wave file**. `T0.2` needs screenshots and `T7.3` requires "a
|
||||
regression test covers the clear-last-constraint path" without naming a home for it — both
|
||||
belong here.
|
||||
|
||||
---
|
||||
|
||||
## Discrepancies
|
||||
|
||||
Things the plan asserts that the repo contradicts. Listed per T0.1's fourth done-when.
|
||||
|
||||
### D1 — "6 pages, 4 stylesheets" is wrong; it is 7 and 6
|
||||
|
||||
`wave-0.md:21` says 6 pages and 4 stylesheets. There are **7 pages and 6 stylesheets**. T0.1's
|
||||
own parenthetical at `wave-0.md:24-25` lists **seven** names, so the document contradicts itself
|
||||
in the same task. The missing stylesheets are `wp-chrome.css` and `wp-sidenav.css`.
|
||||
|
||||
**Consequence:** every "all 6 pages" done-when in waves 2, 3, 5 and 9 is off by one, and `T0.2`
|
||||
asks for "12 baseline screenshots (6 pages x 2 widths)" when the correct number is **14**.
|
||||
14 were captured. Treat "6 pages" as "all pages" wherever it appears.
|
||||
|
||||
### D2 — `A1`'s protected line reference points at the wrong function
|
||||
|
||||
This is the important one. CLAUDE.md, under *Things that must not change*, says:
|
||||
|
||||
> **The logged-override path for predecessors stays (A1).** It is an audited business rule, not
|
||||
> a bug. See `wp-creation-app.js:1962-1972`.
|
||||
|
||||
`IMPLEMENTATION.md`'s `X2` cites the same range. **Lines 1962–1972 are `dashIssue()`**, which is
|
||||
the *opposite* code: the dashboard guard that **refuses** to issue and tells you to
|
||||
"Open the package to release it early with a logged reason". The reviewer read that sentence and
|
||||
correctly concluded a logged override exists — but cited the mention, not the implementation.
|
||||
|
||||
The actual audited path is:
|
||||
|
||||
| Part | Location |
|
||||
|---|---|
|
||||
| **`confirmEarlyRelease()` — the override itself** | **`wp-creation-app.js:967-984`** |
|
||||
| state `pkgGateOverride` | `:392`, reset at `:481`, `:488`, `:1744` |
|
||||
| call site — status change | `:998-1002` |
|
||||
| call site — save | `:1149-1150` |
|
||||
| persisted onto the package | `:1117` (`gateOverride:`) |
|
||||
| rendered in the printed package | `:1215` |
|
||||
| rehydrated when loading a package | `:1674` |
|
||||
| the *guard* the plan actually cited | `:1960-1974` (`dashIssue`) |
|
||||
|
||||
The comment at `:967-969` states the rule plainly: *"Releasing with an unclosed predecessor is
|
||||
allowed but must be explained. The reason rides on the package (`data.gateOverride`) and the
|
||||
server writes it to the audit log."*
|
||||
|
||||
**Consequence for `T7.3`:** the "do not remove" instruction must be applied to **`967-984` and
|
||||
its seven satellites**, not to `1962-1972`. A task that preserved only 1962–1972 would delete the
|
||||
audited business rule while believing it had protected it. `dashIssue()` must also survive — it
|
||||
is what stops the dashboard becoming a quiet way around the gate — but it is a second thing to
|
||||
protect, not the same thing.
|
||||
|
||||
`X2`'s reasoning is unaffected: hold state genuinely is not purely derived from open
|
||||
constraints, so `CR-015` and `A1` remain the same code and the same task.
|
||||
|
||||
### D3 — four documents the plan reads from do not exist yet
|
||||
|
||||
Not errors; they are deliverables not yet produced. Recorded so no task treats one as a missing
|
||||
input and goes looking for a rename.
|
||||
|
||||
| Path | Created by | Also read by |
|
||||
|---|---|---|
|
||||
| `docs/reference/file-map.md` | `T0.1` | `T0.2`, `T1.1`, `T2.1`, `T2.3` |
|
||||
| `docs/reference/tokens.md` | `T3.1` | `T3.2`, `T3.5`, `T9.3` |
|
||||
| `docs/reference/accessibility-audit.md` | `T9.5` | — |
|
||||
| `docs/reference/completion.md` | `T9.7` | — |
|
||||
|
||||
`backlog.md:16` contains `path/to/file.js:120` inside a fenced format template. It is a
|
||||
placeholder, not a reference — do not resolve it.
|
||||
|
||||
### D4 — the creator overflows horizontally at 1440px, not just at 390px
|
||||
|
||||
Measured during `T0.2`, not in the review. Content width against the viewport it was given:
|
||||
|
||||
| Page | 390px | 1440px |
|
||||
|---|---|---|
|
||||
| launcher | 425 | ok |
|
||||
| SOP wizard | 429 | ok |
|
||||
| creator | 485 | **1551** |
|
||||
| field view | 432 | ok |
|
||||
| login, admin, users | ok | ok |
|
||||
|
||||
Four pages overflow at 390px, which is `F2` and its neighbours. The creator also overflows by
|
||||
111px **at desk width**, which no `F` item covers. Logged to `docs/waves/backlog.md`; not fixed
|
||||
here, since wave 1 is scoped to `F1`–`F5` and `T7.x` rebuilds this page anyway.
|
||||
Reference in New Issue
Block a user