Nine of nine exit criteria verified, eight ticked. The ninth is recorded open, deliberately: at rest the creator reads 1,954px / 900px = 2.17 screens against the strict 2.0 encoding of D3's "roughly two screen heights" (down from 5,399px). The criterion was amended once already; whether 2.17 satisfies "roughly" is a product judgment - BL-022 carries the number, the remaining ~154px of chrome, and the question. form_structure_check keeps the strict check red until it is answered. Wave totals: 10 tasks (T7.1-T7.10), 8 new probe suites (frame, form structure, hold, warning, triage, QA gate + capture sink, files + offline, sticky bar, creator dialogs, usage - 305 new checks), one Alembic migration (wp_files), no real email sent anywhere on this branch. Items: B7, F6, D1-D10, CR-015, A1, A2, A6, CR-014, CR-007, B6, S1(creator), D5 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
440 lines
23 KiB
Markdown
440 lines
23 KiB
Markdown
# Wave 7 — The creator
|
|
|
|
**Items:** `B7`, `A1`, `CR-015`, `A2`, `A6`, `CR-014`, `CR-007`, `B6`, `S1` (creator), `F6`,
|
|
and from August 18: `D1`, `D2`, `D3`, `D4`, `D5`, `D8`, `D9`, `D10`
|
|
**Depends on:** wave 6 merged, and `T4.2` (URL state) merged
|
|
**Why last among the build waves:** most of it depends on the iframe decision, and `CR-014`
|
|
depends on `X1`.
|
|
|
|
`T7.1` is the largest engineering item in the plan. Decided and approved: the iframe gets
|
|
dissolved. Do it first - everything after it is cheaper on the far side.
|
|
|
|
**Read `docs/waves/decisions-2026-08-18.md` before starting.** Eight of its ten items land in
|
|
this wave, four of them as changes to done-when lists written below. Where a task carries an
|
|
`Amended` block, that block wins over the text above it.
|
|
|
|
**Read `docs/reference/creator-frame.md` before `T7.1`.** It is the measurement of the
|
|
boundary: 21 colliding stylesheet selectors, 9 colliding script globals, 0 colliding markup
|
|
ids, 28 cross-frame call sites, and the three questions no count can answer.
|
|
|
|
---
|
|
|
|
### T7.1 — B7: Dissolve the creator iframe
|
|
|
|
- **Items:** `B7`, `D1`
|
|
- **Depends on:** T6.5
|
|
- **Blocks:** T7.2 through T7.10
|
|
- **Surface:** `html/`
|
|
- **Files:** parent page hosting the creator, the creator itself, cross-frame messaging
|
|
|
|
**Problem:** The tab row lives in the parent and the toolbar lives in the iframe child, so
|
|
folding one into the other is impossible while the boundary exists. The boundary is also
|
|
implicated in `F4` and possibly in `CR-006` toggle propagation (`X4`).
|
|
|
|
**Do:** Remove the iframe boundary so the creator renders in the parent document. Expect to
|
|
untangle: cross-frame messaging, duplicated styling, focus and scroll management, and
|
|
anything relying on separate document contexts.
|
|
|
|
Do this as its own PR with no feature work attached. It will be large and it needs to be
|
|
reviewable as a structural change.
|
|
|
|
**Do not:** bundle any other item into this task, and do not leave a dormant iframe path
|
|
behind a flag.
|
|
|
|
**Amended August 18 (`D1`, `D5`).** `creator-frame.md` section 4 lists three questions this
|
|
task has to settle. Two are now answered:
|
|
|
|
- **Does the creator get the app bar back?** Yes. It is the only page in `html/` that loads
|
|
neither `wp-chrome.css` nor `wp-chrome.js`, and a page without the app bar is not a page.
|
|
Expect to redo the wizard's layout arithmetic - `chromeHeight()`, `--wp-chrome-h`, the
|
|
`embed-full` sizing.
|
|
- **What happens to `body.embedded`?** It goes, and with it `.embed-hide`. The three controls
|
|
it was hiding: the creator's own header stays hidden because the app bar replaces it; the
|
|
**sample-data control becomes visible** (`D1`); the analytics button stays visible here and
|
|
**moves to the admin console at `T7.10`** (`D5`). Do not delete it in this task - a task
|
|
that both dissolves the frame and deletes a feature is two diffs.
|
|
- **One sequence component or two?** Still open, and still this task's call. Nine of the 21
|
|
colliding selectors are the sequence editor. The wizard authors the sequence and the creator
|
|
renders it; confirmed August 18 that those stay two adjustable things, which argues for
|
|
scoping rather than merging. If you scope, say so and leave `BL-015` open for wave 9.
|
|
|
|
**Do not** fold `BL-001`, `BL-006`, `BL-007` or `BL-013` into this diff. They are logged
|
|
against this file and they are cheaper now than ever, and they are still separate items. What
|
|
this task owes them is a **measurement**: record whether each still reproduces after the
|
|
rebuild, so `T7.2` and `T9.5` inherit a fact rather than an assumption.
|
|
|
|
**Done when:**
|
|
|
|
- [ ] no iframe remains in the creator; grep confirms
|
|
- [ ] every creator feature works as it did before: verify against the wave 0 baseline screenshots and a functional pass
|
|
- [ ] `F4` no longer reproduces
|
|
- [ ] `CR-006` section toggles propagate into the creator with no special-casing
|
|
- [ ] browser back and forward still behave with the `T4.2` URL state
|
|
- [ ] no cross-frame messaging code remains
|
|
- [ ] the creator renders the standard app bar, and the wizard's chrome arithmetic still holds at 390px and 1440px
|
|
- [ ] `body.embedded` and `.embed-hide` are gone; grep confirms
|
|
- [ ] the sample-data control is visible and reachable on the creator (`D1`)
|
|
- [ ] `BL-001`, `BL-006`, `BL-007` and `BL-013` are each re-measured after the rebuild and their entries updated with the result
|
|
|
|
---
|
|
|
|
### T7.2 — F6 + D3: Side navigation and collapsible sections replace the 4,700px form
|
|
|
|
- **Items:** `F6`, `D3`
|
|
- **Depends on:** T7.1, T5.5, T3.5
|
|
- **Blocks:** T7.9
|
|
- **Surface:** `html/`
|
|
- **Files:** creator layout, jump links
|
|
|
|
**Problem:** The creator is one form roughly 4,700px tall with 11 cards rendered at once and
|
|
jump links standing in for structure.
|
|
|
|
**Do:** Give the form real structure — section tabs or an equivalent that shows one coherent
|
|
group at a time. Respect the `CR-006` toggles: a section toggled off has no tab. Retire the
|
|
jump links. Section identity belongs in the URL (`T4.2`) so a section is linkable.
|
|
|
|
**Amended August 18 (`D3`) - the answer is not tabs.** Asked to choose, the decision was one
|
|
page with navigation down the side; asked about the height conflict that creates, the call was
|
|
delegated. Adopted: **one page, persistent side navigation, sections collapsible, only the
|
|
current one open by default, plus an `Expand all`.** Tabs were rejected because they hide
|
|
sections a first-time author does not know exist. An uncollapsed long form was rejected
|
|
because it is the 4,700px page `F6` exists to fix. The done-when list below is the amended
|
|
one; it replaces four of the six entries as written.
|
|
|
|
`BL-013` is folded in here and only here: the creator's inputs have `outline: none` with a
|
|
1.05:1 glow as their only focus cue, which is a standing `CLAUDE.md` violation on the page
|
|
with the most form controls in the app. A rebuilt form ships the `T3.4` ring or it is not
|
|
done.
|
|
|
|
**Done when:**
|
|
|
|
- [ ] no single view exceeds roughly two screen heights at 1440px **at rest** - that is, in the default collapse state the page loads in
|
|
- [ ] toggled-off sections have no entry in the side navigation
|
|
- [ ] each section is addressable by URL and survives refresh
|
|
- [ ] jump links are gone
|
|
- [ ] the side navigation is keyboard operable and marks the current section with `aria-current`
|
|
- [ ] each section header is a real `<button>` with `aria-expanded`, not a `<div>` with a click handler
|
|
- [ ] `Expand all` and its inverse exist and are keyboard reachable
|
|
- [ ] deep-linking to a collapsed section expands it
|
|
- [ ] unsaved work is preserved when moving between sections (`T4.3`)
|
|
- [ ] every focusable control on the page draws a ring of at least 3:1 against its background (`BL-013`)
|
|
|
|
---
|
|
|
|
### T7.3 — A1 + CR-015: Guarded transitions and the hold bug
|
|
|
|
- **Items:** `A1`, `CR-015`, `D4`
|
|
- **Depends on:** T7.1
|
|
- **Blocks:** T7.4, T7.6
|
|
- **Surface:** `server/` + `html/`
|
|
- **Files:** status handling, constraint handling, `confirmEarlyRelease()` in `wp-creation-app.js`
|
|
|
|
**This is one task, not two (`X2`).** The hold-not-clearing bug and the transition model are
|
|
the same code. `CR-015` is the highest-severity item in the plan and it was reproduced live
|
|
in front of the Micron team.
|
|
|
|
**Problem:** Clearing all constraints does not clear the hold. Hold state is not purely
|
|
derived from open constraints, which is why it goes stale.
|
|
|
|
**Do:** Model transitions explicitly. For each state, define the primary next action **plus
|
|
an audited override**. "One legal next action" is too narrow - `confirmEarlyRelease()` in
|
|
`wp-creation-app.js` is a deliberate logged-override path for predecessors, and Issue (Hold)
|
|
is a branch from several states, not a single linear step.
|
|
|
|
**Corrected August 18.** This task's file list, `IMPLEMENTATION.md` `X2` and `CLAUDE.md` all
|
|
cited `wp-creation-app.js:1962-1972` as the protected override path. Those lines are
|
|
`deletePackage()` and `clearSaved()` - a different rule entirely. The path to preserve is
|
|
`confirmEarlyRelease()`, called from the issue and release paths. All three documents now name
|
|
it by function so the reference survives this rebuild.
|
|
|
|
Derive hold state from open constraints rather than storing it independently, or if it must
|
|
be stored, recalculate it on every constraint change. Write every hold and release to the
|
|
work package history with timestamp, user and reason.
|
|
|
|
**Do not:** remove the logged-override path. It is an audited business rule. And do not fix
|
|
the symptom by recalculating on page load only.
|
|
|
|
**Done when:**
|
|
|
|
- [ ] clearing the last open constraint clears the hold and returns the work package to its prior status, with no refresh
|
|
- [ ] logging a new constraint on an in-progress work package places it back on hold
|
|
- [ ] clearing that constraint releases it again
|
|
- [ ] the override path still works and still logs
|
|
- [ ] Issue (Hold) is reachable from every state it should branch from
|
|
- [ ] every hold and release is in the history with timestamp, user and reason
|
|
- [ ] a regression test covers the clear-last-constraint path specifically
|
|
- [ ] the exact root cause is stated in the PR
|
|
|
|
**Amended August 18 (`D4`) - what `Urgent` does.** Asked whether an `Urgent` package should be
|
|
issuable with an open constraint, the first answer was "maybe". The concern raised back was
|
|
that a silent bypass destroys the delay-documentation use case that justifies the whole
|
|
constraint workflow: a constraint log that can be shown to have been skipped stops supporting
|
|
a notice of delay. Confirmed: **surface the audited path, do not add a new one.**
|
|
|
|
- [ ] an `Urgent` package with an open constraint offers `confirmEarlyRelease()` in the primary action position, not behind a secondary control
|
|
- [ ] taking it still writes actor, timestamp and reason to history
|
|
- [ ] no code path releases a constrained package without writing that entry; verify by grep and by driving it
|
|
- [ ] a `Normal` or `High` package is unchanged - the override is no more prominent than it is today
|
|
|
|
**Why the history matters:** the delay-documentation use case is the business justification
|
|
for the whole constraint workflow. If a constraint log can be shown to have been wrong, it
|
|
stops supporting a notice of delay or a change order claim.
|
|
|
|
---
|
|
|
|
### T7.4 — A2: De-duplicate the constraint warning
|
|
|
|
- **Items:** `A2`
|
|
- **Depends on:** T7.3
|
|
- **Blocks:** nothing
|
|
- **Surface:** `html/`
|
|
- **Files:** creator constraint warnings
|
|
|
|
**Problem:** The same warning appears three times.
|
|
|
|
**Do:** Keep one. The top banner is the only one visible without scrolling, so it stays. The
|
|
tab count badge then has to carry the weight the removed duplicates were carrying — make the
|
|
count prominent enough to notice from any section.
|
|
|
|
**Done when:**
|
|
|
|
- [ ] the warning appears once
|
|
- [ ] the tab badge shows the open constraint count and is legible at 390px
|
|
- [ ] with the constraints section scrolled out of view, a user can still tell constraints are open
|
|
- [ ] the banner announces via `aria-live` when the count changes
|
|
|
|
---
|
|
|
|
### T7.5 — A6: Sidebar triage data and inline hold reason
|
|
|
|
- **Items:** `A6`
|
|
- **Depends on:** T7.3
|
|
- **Blocks:** nothing
|
|
- **Surface:** `html/`
|
|
- **Files:** creator sidebar
|
|
|
|
**Do:** Surface triage data in the sidebar, including the hold reason inline. The hold reason
|
|
is already captured by the hold modal, so this is display work.
|
|
|
|
**Use case to test against:** someone in a stand-up is asked why a package has not moved.
|
|
They open it on a phone and need the answer without scrolling or clicking.
|
|
|
|
**Done when:**
|
|
|
|
- [ ] the hold reason is visible in the sidebar without opening the modal
|
|
- [ ] status, priority, due date, P6 activity and open constraint count are all visible together
|
|
- [ ] usable at 390px
|
|
- [ ] a package with no hold shows a sensible state rather than an empty slot
|
|
|
|
---
|
|
|
|
### T7.6 — CR-014: Ready for QA gate
|
|
|
|
- **Items:** `CR-014`, `D2`, `D9`, `D10`
|
|
- **Depends on:** T7.3, T4.2 (blocking dependency `X1`), and the wave 5 SOP wizard for the `D2` field
|
|
- **Blocks:** nothing
|
|
- **Surface:** `server/` + `html/`
|
|
- **Files:** status model, notification service, QA section
|
|
|
|
**Intent:** Looping QA in has historically been the failure point. Marlena raised this
|
|
directly: QA needs to see inbound work and organize their schedule ahead of time rather than
|
|
being told after the fact.
|
|
|
|
**Do:** Add `Ready for QA` between In Progress and Complete/Closed, inside the `T7.3`
|
|
transition model (`X3`). Entering that state emails the assigned QA representative and the
|
|
QA/QC members named on the work package.
|
|
|
|
The email includes the work package number and title, location, a scope summary, and **a
|
|
direct link that opens that work package** — this is why `T4.2` is a hard prerequisite. A
|
|
dashboard view lists everything sitting in Ready for QA. The QA representative can accept or
|
|
reject; rejection returns the package to In Progress with a required comment.
|
|
|
|
**Do not:** build the email with a link to the app root. That is the failure `X1` exists to
|
|
prevent.
|
|
|
|
**Amended August 18 (`D2`, `D9`, `D10`).** Three answers change this task:
|
|
|
|
- **Who receives it.** Not "the QA rep and the QA/QC members named on the work package" -
|
|
**the QA group, configured once during SOP setup as a dropdown of project members.** That
|
|
makes the recipient list SOP configuration, so this task acquires a wizard field and a
|
|
dependency on wave 5 that it did not have.
|
|
- **Who hears about a rejection.** The **work package owner and the same distribution list**,
|
|
not only the submitter.
|
|
- **Where the state is visible.** The dashboard **and Field View**.
|
|
- **Who turns email on.** An administrator, from `admin.html`. The gate is a stored setting,
|
|
not an environment variable. It ships **off** and is verified against a capture sink; no
|
|
real mail is sent from this branch.
|
|
|
|
**Done when:**
|
|
|
|
- [ ] the new state exists in the transition model, not beside it
|
|
- [ ] the QA distribution list is chosen in the SOP wizard from project members and persists
|
|
- [ ] entering `Ready for QA` emails that list and nobody else
|
|
- [ ] rejection emails the work package owner and the same list
|
|
- [ ] the link in the email opens that specific work package, including for a signed-out recipient via login
|
|
- [ ] a dashboard view or filter lists all packages in Ready for QA
|
|
- [ ] Field View shows which packages are in `Ready for QA`, legibly at 390px, with something other than colour carrying the state (`D9`)
|
|
- [ ] rejection returns to In Progress and requires a comment
|
|
- [ ] the transition is written to history
|
|
- [ ] email failure is logged and surfaced, not silent
|
|
- [ ] the send path is exercised end to end against a capture sink, with the count of captured messages asserted
|
|
- [ ] the default is off; an administrator can turn it on from `admin.html` and a non-administrator cannot (`D10`)
|
|
- [ ] changing the setting is written to the audit log
|
|
- [ ] no SMTP password appears anywhere outside the environment, and no customer IP appears in a message body
|
|
|
|
**Note:** QA currently runs off a comprehensive Excel questionnaire being migrated into
|
|
CxAlloy. Integration with CxAlloy is explicitly out of scope. This gate is notification only.
|
|
|
|
---
|
|
|
|
### T7.7 — CR-007: Upload drawings for offline access
|
|
|
|
- **Items:** `CR-007`, `D8`
|
|
- **Depends on:** T7.2, T4.3 (blocking dependency `X8`)
|
|
- **Blocks:** nothing
|
|
- **Surface:** `server/` + `html/`
|
|
- **Files:** Drawings and Attachments section, file storage, export
|
|
|
|
**Intent:** Today the section holds links, typically to a Bluebeam session. The field wants
|
|
the specific PDF attached instead: a general foreman opens the package and sees exactly the
|
|
sheet and the highlighted section relevant to their scope, with no navigation and no
|
|
connectivity dependency. Links stay supported for those who want them.
|
|
|
|
**Do:** File upload alongside the existing link support. Store files with the work package.
|
|
Include them when the package is exported or downloaded. Make them available offline on a
|
|
tablet. Each attachment gets a short description field so the creator can note the focus
|
|
area, for example "Tray section, Level 3 east only".
|
|
|
|
Show file size limits and supported types in the UI before upload, not after failure.
|
|
|
|
**Do not:** build this before `T4.3`. Uploading into a form with no autosave risks losing
|
|
both the upload and the surrounding work.
|
|
|
|
**Amended August 18 (`D8`) - the numbers.** `CR-007` says "show file size limits and supported
|
|
types" without saying what they are. They are: **5MB a file, PDFs and images, stored in the
|
|
same database as everything else.** Offline caching covers **only the packages assigned to
|
|
the requesting user**, not the whole project.
|
|
|
|
The consequence was raised and settled rather than discovered later: files in the database
|
|
means every encrypted backup carries them. Splitting them out was rejected - a backup that
|
|
excludes the drawings is a backup you cannot restore from - so a **2GB per-project ceiling**
|
|
was approved instead, with a warning at 80%.
|
|
|
|
**Done when:**
|
|
|
|
- [ ] PDF upload works and the file is retrievable
|
|
- [ ] image upload works and the file is retrievable
|
|
- [ ] links still work alongside uploads
|
|
- [ ] attachments are included in export or download
|
|
- [ ] an uploaded drawing opens on a tablet with the network disabled
|
|
- [ ] offline caching covers the requesting user's assigned packages only; verify a package assigned to someone else is not cached
|
|
- [ ] the description field persists and prints on the export
|
|
- [ ] limits and supported types are stated before upload
|
|
- [ ] a file over 5MB is refused before upload, naming the limit
|
|
- [ ] a type outside PDF and image is refused before upload, naming the accepted types
|
|
- [ ] a project at 80% of 2GB warns; at 2GB it refuses, naming the ceiling
|
|
- [ ] the running project total is visible where uploads happen
|
|
- [ ] both limits are enforced on the server, not only in the browser
|
|
- [ ] upload failure is clear and recoverable, with no loss of surrounding form work
|
|
- [ ] the whole flow works at 390px
|
|
|
|
**Accepted tradeoff:** this shifts effort onto the package creator to isolate the right
|
|
sheet. That was raised in the meeting and accepted.
|
|
|
|
---
|
|
|
|
### T7.8 — B6: Sticky action bar
|
|
|
|
- **Items:** `B6`
|
|
- **Depends on:** T7.2
|
|
- **Blocks:** nothing
|
|
- **Surface:** `html/`
|
|
- **Files:** creator and wizard action bars
|
|
|
|
**Problem:** The proposal placed actions beside the fields, but on the Constraints and
|
|
Sequence steps that means scrolling to save.
|
|
|
|
**Do:** A sticky action bar instead. The creator already solves this; reuse that pattern in
|
|
the wizard rather than inventing a second one.
|
|
|
|
**Done when:**
|
|
|
|
- [ ] save and primary actions are reachable without scrolling on every step and section
|
|
- [ ] verified specifically on Constraints and Sequence
|
|
- [ ] the bar does not obscure fields at 390px
|
|
- [ ] it shows the save state from `T4.4`
|
|
|
|
---
|
|
|
|
### T7.9 — S1 (creator): Inline validation
|
|
|
|
- **Items:** `S1` creator half
|
|
- **Depends on:** T7.2
|
|
- **Blocks:** nothing
|
|
- **Surface:** `html/`
|
|
- **Files:** creator validation, `wp-creation-app.js:1144`
|
|
|
|
**Problem:** 43 native dialogs in the creator alone. `wp-creation-app.js:1144` says "Subject
|
|
and WP Type are required" without naming, highlighting or scrolling to the field, on a form
|
|
ten cards deep.
|
|
|
|
**Do:** Inline validation matching the wizard pattern from `T5.8`. Errors at the field, focus
|
|
and scroll to the first invalid one, and with section tabs now in place, the tab containing
|
|
errors is marked. Remove the creator's native dialogs.
|
|
|
|
**Done when:**
|
|
|
|
- [ ] no `alert()`, `confirm()` or `prompt()` remains in the creator; count is 0
|
|
- [ ] every required field validates inline
|
|
- [ ] submitting focuses and scrolls to the first error, switching sections if needed
|
|
- [ ] sections containing errors are marked in the tab row
|
|
- [ ] errors announce via `aria-live`
|
|
- [ ] the app-wide native dialog count is recorded against the wave 0 baseline of 79
|
|
|
|
---
|
|
|
|
### T7.10 — D5: Usage data moves to the admin console
|
|
|
|
- **Items:** `D5`
|
|
- **Depends on:** T7.1
|
|
- **Blocks:** nothing
|
|
- **Surface:** `html/`
|
|
- **Files:** `admin.html`, `admin.js`, `wp-creation-app.js`, `work-package-suite-app.js`
|
|
|
|
**Problem:** Usage analytics exists **twice**. `creator-frame.md` section 2b counts five of
|
|
the nine colliding script globals as this one feature - `ANALYTICS_KEY`, `analyticsLoad`,
|
|
`analyticsSave`, `downloadAnalytics`, `showAnalytics` - and records that the wizard's copy has
|
|
no caller, because the button that opens it lives on the creator. Once the frame is gone, two
|
|
implementations sit in one document.
|
|
|
|
**Do:** Keep one implementation and put its entry point in the admin console, where an
|
|
operator-facing report belongs. Remove the analytics control from the creator and from the
|
|
wizard. This is not a rewrite of what analytics collects - the same data, reached from one
|
|
place instead of a button on a package-authoring screen.
|
|
|
|
**Do not:** change what is tracked, and do not leave the second implementation behind
|
|
unreferenced. An unreferenced duplicate is what produced this item.
|
|
|
|
**Done when:**
|
|
|
|
- [ ] usage data is reachable from `admin.html`
|
|
- [ ] no analytics control remains on the creator or the wizard; grep confirms
|
|
- [ ] exactly one implementation of `analyticsLoad`/`analyticsSave`/`downloadAnalytics` survives; grep confirms
|
|
- [ ] the data recorded before this task is still readable after it
|
|
- [ ] the console entry point is behind the same role check as the rest of `admin.html`
|
|
- [ ] the report is usable at 390px
|
|
|
|
---
|
|
|
|
## Wave 7 exit criteria
|
|
|
|
- [x] no iframe; `F4` resolved structurally (`frame_check.py`, 39 checks)
|
|
- [x] `CR-015` fixed with a regression test and a stated root cause (`hold_check.py`; the cause is in the T7.3 commit, both halves - `prevStatus` destroyed client-side, `_released('Issue')` true server-side)
|
|
- [x] hold state is derived, and history records every transition (client `data.holds`, server `hold_logged`/`hold_released` audit rows on both write paths)
|
|
- [x] the QA gate emails a working deep link, to the SOP-configured list, with the gate off by default (`qa_gate_check.py` against the capture sink)
|
|
- [x] drawings upload and open offline on a tablet, inside the 5MB and 2GB limits (`files_check.py`; the offline half runs against a genuinely killed server)
|
|
- [x] creator native dialog count is 0 (`creator_dialogs_check.py`; app-wide count printed against the wave 0 baseline of 79)
|
|
- [ ] the creator is a page: app bar, side navigation, collapsible sections, focus rings — all shipped — but **at rest it reads 1,954px against a 900px viewport: 2.17 screens against the strict 2.0 encoding of "roughly two screen heights."** Down from 5,399px. Whether 2.17 satisfies "roughly two" is a product judgment, deliberately not made here after the criterion was already amended once (`D3`); `BL-022` carries the remaining ~154px of page chrome and the question. `form_structure_check.py` keeps the strict check red until it is answered.
|
|
- [x] `D1` through `D5`, `D8`, `D9` and `D10` are each satisfied (D1 T7.1, D2/D9/D10 T7.6, D3 T7.2, D4 T7.3, D5 T7.10, D8 T7.7)
|
|
- [x] no real email left this branch; the capture sink count is recorded (every send in `qa_gate_check.py` terminates at an in-process SMTP sink; counts and recipients asserted)
|