Wave 7 prep - record the Aug 18 decisions as D1-D10 and amend the waves
Nick answered 21 questions at the wave 6 exit and 11 follow-ups. Seven answers are new build work, three amend acceptance criteria on tasks already scheduled, and two close questions without work. None of it had an item ID, so none of it could be built under CLAUDE.md's first rule. New items D1-D10 in docs/waves/decisions-2026-08-18.md. A new prefix rather than widened CR/F/S/A/B/C numbers - those are referenced in documents outside this repo and CLAUDE.md forbids reinterpreting them. Every D entry names the item it amends and quotes the criterion it replaces, so a reader of R2 can see what moved. D1 sample data returns to the creator B7, S7 T7.1 D2 QA distribution list configured in the SOP CR-014 T7.6 D3 side navigation and collapsible sections, not tabs F6 T7.2 D4 Urgent surfaces the audited override, never bypasses CR-003/A1 T7.3 D5 usage data moves to the admin console B7 T7.10 (new) D6 material list uploads at SOP configuration CR-013 T8.6 (new) D7 archived projects readable by project admins B3, C1 T9.8 (new) D8 5MB a file, 2GB a project, PDFs and images, one DB CR-007 T7.7 D9 Ready for QA appears in Field View CR-014 T7.6 D10 email switched on and off from the admin console CR-011/14 T7.6, T8.3 Two decisions were mine to make and are recorded as such. D3: the written F6 criterion (no view over two screen heights) and the answer (one long form with side nav) cannot both hold, so the criterion now reads 'at rest' and sections collapse by default - tabs hide sections a first-time author does not know exist. D8: keeping 5MB files in the same database means every encrypted backup carries them; splitting them out was rejected because a backup without the drawings cannot restore, so a 2GB per-project ceiling was approved instead. Also corrected, not amended: CLAUDE.md and IMPLEMENTATION.md X2 both cited wp-creation-app.js:1962-1972 as the protected logged-override path that T7.3 is forbidden to remove. Those lines are deletePackage() and clearSaved(). The path is confirmEarlyRelease() at :1002. Both documents now name it by function so the reference survives the T7.1 rewrite that is about to move it. Wave 9 gains T9.9, a sweep of the nine backlog entries that name wave 9 as their home. Left unscheduled they surface at T9.7, which has no room to fix anything. The four colour items in it (BL-004/005/008/009) are now approved work. T9.5's help-tip count corrected from 15 to 18 and dated: three were added during waves 5 and 6 by tasks reusing the component as designed, each unreachable for the same reason. Scheduling a broken component late makes every reuse cost more. Closed without work: the free-text location migration. Every location on record is sample data because no real list has been loaded, so there is nothing to migrate. Recorded with the condition that invalidates it - the first real project - so it is a decision rather than a surprise. Items: D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 Task: T7.0 (wave 7 prep) Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
12
CLAUDE.md
12
CLAUDE.md
@@ -5,13 +5,15 @@ any task, and read the wave file for the task you are on. Do not work from this
|
||||
|
||||
## The spec is the source of truth
|
||||
|
||||
Every change traces to an item ID (`CR-001`, `F1`, `S1`, `A1`, `B1`, `C1`). If you are about
|
||||
Every change traces to an item ID (`CR-001`, `F1`, `S1`, `A1`, `B1`, `C1`, `D1`). If you are about
|
||||
to make a change that has no ID, stop. Either it belongs to an existing item and you should
|
||||
say which, or it is out of scope and should be logged in `docs/waves/backlog.md` instead of
|
||||
built.
|
||||
|
||||
Do not renumber, merge, or reinterpret item IDs. They are referenced in documents outside
|
||||
this repo that other people are reading.
|
||||
this repo that other people are reading. New scope decided mid-build gets a **new** ID rather
|
||||
than a widened old one - that is what the `D` prefix is for. See
|
||||
`docs/waves/decisions-2026-08-18.md`.
|
||||
|
||||
## Scope discipline
|
||||
|
||||
@@ -51,7 +53,11 @@ These are recorded decisions, not oversights. Do not "clean them up":
|
||||
- **Uppercase card headers in `console.css` stay (A5).** The sentence-case rule applies to
|
||||
buttons and field labels only. The uppercase header idiom is deliberate.
|
||||
- **The logged-override path for predecessors stays (A1).** It is an audited business rule,
|
||||
not a bug. See `wp-creation-app.js:1962-1972`.
|
||||
not a bug. It is `confirmEarlyRelease()` in `wp-creation-app.js`, called from the issue and
|
||||
release paths. Named by function, not by line: this file and `IMPLEMENTATION.md` X2 both
|
||||
cited `wp-creation-app.js:1962-1972` until Aug 18 2026, and those lines are
|
||||
`deletePackage()`/`clearSaved()` - a different rule entirely. Corrected before T7.3, which
|
||||
is the task told not to remove it.
|
||||
- **Removed fields are hidden, not deleted (CR-002, CR-016).** Retain the data and the model.
|
||||
Removal is expressed through the CR-006 section toggles.
|
||||
|
||||
|
||||
@@ -5,6 +5,9 @@ Companion document for humans: `WorkPackageSuite_Consolidated_Change_Request_R2.
|
||||
|
||||
55 items, 9 waves, dependency-ordered. Read `CLAUDE.md` first.
|
||||
|
||||
Ten further items (`D1`-`D10`) were decided on August 18 2026 and are recorded in
|
||||
`docs/waves/decisions-2026-08-18.md`. 65 items total.
|
||||
|
||||
---
|
||||
|
||||
## 1. Where this came from
|
||||
@@ -33,9 +36,26 @@ decision. Do not reopen these without a spec revision.
|
||||
| `B7` | **Dissolve the creator iframe.** Scheduled as `T7.1`, the first task of wave 7. This is the largest engineering item in the plan and most of wave 7 depends on it. |
|
||||
| `C1` | **Accessibility is in scope.** Fold it into components already being rebuilt rather than treating it as a separate pass. Rules are in `CLAUDE.md`. |
|
||||
|
||||
> If the `B7` decision was meant as "schedule the decision" rather than "dissolve the
|
||||
> iframe", that is the one line in this plan to correct before wave 7 starts. Everything
|
||||
> before wave 7 is unaffected either way.
|
||||
> `B7` was confirmed as "dissolve the iframe" on August 14 2026 and again at the wave 7
|
||||
> handoff. It is not a scheduling decision.
|
||||
|
||||
**A second set of decisions closed on August 18 2026**, at the wave 6 exit, in answer to
|
||||
twenty-one questions and eleven follow-ups. They are recorded in
|
||||
`docs/waves/decisions-2026-08-18.md` as `D1`-`D10`. They add three tasks and amend
|
||||
acceptance criteria on seven others; they do not reopen anything above.
|
||||
|
||||
| ID | Decision | Amends |
|
||||
|---|---|---|
|
||||
| `D1` | Sample data returns to the creator, visible on the unframed page | `B7`, `S7` |
|
||||
| `D2` | The QA distribution list is configured in the SOP, not per work package | `CR-014` |
|
||||
| `D3` | The creator stays one page: side navigation plus collapsible sections | `F6` |
|
||||
| `D4` | `Urgent` surfaces the audited override; it does not bypass the constraint gate | `CR-003`, `A1` |
|
||||
| `D5` | Usage data moves to the admin console | `B7` |
|
||||
| `D6` | The material list uploads at SOP configuration | `CR-013` |
|
||||
| `D7` | Archived projects are readable, by project admins only | `B3`, `C1` |
|
||||
| `D8` | 5MB a file, 2GB a project, PDFs and images, stored in the same database | `CR-007` |
|
||||
| `D9` | `Ready for QA` appears in Field View | `CR-014` |
|
||||
| `D10` | Email is switched on and off from the admin console | `CR-011`, `CR-014` |
|
||||
|
||||
## 3. Cross-track dependencies
|
||||
|
||||
@@ -45,7 +65,7 @@ be built as written, or cannot be built once, until something else lands.
|
||||
| ID | Item | Depends on | Type | Why |
|
||||
|---|---|---|---|---|
|
||||
| `X1` | `CR-011`, `CR-014` | `S3` | **Blocking** | Both promise an email containing a direct link to the work package. There is no `pushState` anywhere in the app, so no work package has an addressable URL. The emails cannot be built until URL state exists. |
|
||||
| `X2` | `CR-015` | `A1` | **Blocking** | The hold-not-clearing bug and the transition model are the same code. `wp-creation-app.js:1962-1972` shows a deliberate logged-override path, so hold state is not purely derived from open constraints. Fixing them separately means fixing it twice. |
|
||||
| `X2` | `CR-015` | `A1` | **Blocking** | The hold-not-clearing bug and the transition model are the same code. `confirmEarlyRelease()` in `wp-creation-app.js` is a deliberate logged-override path, so hold state is not purely derived from open constraints. Fixing them separately means fixing it twice. **Corrected Aug 18 2026:** this row and `CLAUDE.md` both cited `wp-creation-app.js:1962-1972`, which is `deletePackage()`/`clearSaved()`. The override path is `confirmEarlyRelease()`, called from the issue and release paths. Named by function so it survives the `T7.1` rewrite. |
|
||||
| `X3` | `CR-014` | `A1` | Sequencing | `Ready for QA` is a new state and must land inside the guarded transition model, not beside it. |
|
||||
| `X4` | `CR-006` | `B7` | Sequencing | Section toggles must suppress sections inside the creator, which is an iframe child until `T7.1`. |
|
||||
| `X5` | `CR-004`, `CR-018` | `B4` | **Blocking** | Rollup by building, floor and sector cannot come from `localStorage`. Same data dependency that blocks the pipeline strip. |
|
||||
@@ -66,9 +86,9 @@ be built as written, or cannot be built once, until something else lands.
|
||||
| 4 | Platform prerequisites | `docs/waves/wave-4.md` | `B4` `S3` `S2` `B5` `S10` `S11` `S12` |
|
||||
| 5 | Launcher and SOP wizard | `docs/waves/wave-5.md` | `A4` `B3` `S9` `CR-005` `CR-006` `CR-002` `CR-016` `S1`(wizard) |
|
||||
| 6 | Work package general information | `docs/waves/wave-6.md` | `CR-001` `CR-003` `CR-004` `CR-018` `A7` |
|
||||
| 7 | The creator | `docs/waves/wave-7.md` | `B7` `A1` `CR-015` `A2` `A6` `CR-014` `CR-007` `B6` `S1`(creator) `F6` |
|
||||
| 8 | Kitting and material | `docs/waves/wave-8.md` | `CR-009` `CR-010` `CR-011` `CR-012` `CR-013` |
|
||||
| 9 | Verification and cleanup | `docs/waves/wave-9.md` | `CR-008` `CR-017` `S6` `S7` `C1` `C2` `C4` |
|
||||
| 7 | The creator | `docs/waves/wave-7.md` | `B7` `A1` `CR-015` `A2` `A6` `CR-014` `CR-007` `B6` `S1`(creator) `F6` `D1` `D2` `D3` `D4` `D5` `D8` `D9` `D10` |
|
||||
| 8 | Kitting and material | `docs/waves/wave-8.md` | `CR-009` `CR-010` `CR-011` `CR-012` `CR-013` `D6` `D10` |
|
||||
| 9 | Verification and cleanup | `docs/waves/wave-9.md` | `CR-008` `CR-017` `S6` `S7` `C1` `C2` `C4` `D7` |
|
||||
|
||||
**Waves 1 through 4 produce almost no field-visible change.** That is deliberate and it is
|
||||
roughly the first third of the effort. It is called out here because the Micron team is
|
||||
@@ -132,6 +152,19 @@ Every one of the 55 items appears in exactly one wave, except where noted.
|
||||
| CR-018 | 6 | S12 | 4 | C4 | 4 and 9 |
|
||||
| | | S13 | 1 | | |
|
||||
|
||||
### The August 18 items
|
||||
|
||||
| Item | Wave | Task | Item | Wave | Task |
|
||||
|---|---|---|---|---|---|
|
||||
| D1 | 7 | T7.1 | D6 | 8 | T8.6 |
|
||||
| D2 | 7 | T7.6 | D7 | 9 | T9.8 |
|
||||
| D3 | 7 | T7.2 | D8 | 7 | T7.7 |
|
||||
| D4 | 7 | T7.3 | D9 | 7 | T7.6 |
|
||||
| D5 | 7 | T7.10 | D10 | 7 and 8 | T7.6, T8.3 |
|
||||
|
||||
That is 65 items across 9 waves. `D10` is the only one split across two waves: the gate and
|
||||
its console control are built once at `T7.6` and reused by `T8.3`.
|
||||
|
||||
`F5` and `A3` are the same defect from two sources. `C1` and `C2` are standing requirements
|
||||
enforced per task under `CLAUDE.md`, with a dedicated audit in wave 9. `CR-017` is a
|
||||
do-not-remove guard rather than a build.
|
||||
@@ -161,3 +194,11 @@ them; do not invent placeholder values in their absence.
|
||||
|
||||
Where a list is required and not yet supplied, build the upload path (`CR-005`) and seed with
|
||||
an obviously-fake sample. Do not hardcode guessed floor names.
|
||||
|
||||
**Status, August 18 2026.** None of the four has arrived. Confirmed at the wave 6 exit that
|
||||
this does not change the plan: `D6` extends the `CR-005` upload pattern to the material list
|
||||
so `CR-013` is buildable without Nate's spreadsheet, and the B100 list is still expected
|
||||
through the same door. Because no real list has ever been loaded, every location on record
|
||||
is sample data - which is why the free-text migration question was closed without work
|
||||
(`decisions-2026-08-18.md`, "Closed without work"). That answer does not survive the first
|
||||
real project.
|
||||
|
||||
273
docs/waves/decisions-2026-08-18.md
Normal file
273
docs/waves/decisions-2026-08-18.md
Normal file
@@ -0,0 +1,273 @@
|
||||
# Decisions — August 18, 2026
|
||||
|
||||
Approved by Nick Siegfried during wave 7 planning, in answer to twenty-one questions raised
|
||||
at the wave 6 exit and eleven follow-ups.
|
||||
|
||||
These are **new items**, not reinterpretations of existing ones. `CLAUDE.md` forbids
|
||||
renumbering or reinterpreting `CR`/`F`/`S`/`A`/`B`/`C` IDs because they are referenced in
|
||||
documents outside this repo, so everything decided here gets its own `D` prefix and each
|
||||
entry names the existing item it amends. Where a `D` item changes an acceptance criterion,
|
||||
the original criterion is quoted and the replacement is stated, so a reader of the R2
|
||||
document can see exactly what moved.
|
||||
|
||||
Ten items. Seven are new build work; three amend criteria on work already scheduled.
|
||||
|
||||
---
|
||||
|
||||
## D1 — Sample data returns to the creator
|
||||
|
||||
- **Amends:** `B7` (`T7.1`), `S7` (`T9.4`)
|
||||
- **Surface:** `html/`
|
||||
|
||||
`wp-creation-styles.css` opens with `body.embedded .embed-hide { display: none }` — framed,
|
||||
the creator hides its own header, its sample-data controls and its analytics button. `T7.1`
|
||||
dissolves the frame, so "framed" stops being a state and those three controls need a home or
|
||||
a deletion. Decided: **the sample-data control comes back and is visible.**
|
||||
|
||||
That collides with `S7`, which reduces four sample-data affordances under three names to one.
|
||||
It is not a contradiction: `S7`'s complaint is that there are four of them, that they are
|
||||
named inconsistently, and that one sits a click from live project data. A single, clearly
|
||||
named, confirmed affordance on the creator satisfies both. `T9.4` owns making it the only
|
||||
one; `T7.1` owns making it visible.
|
||||
|
||||
**Done when:** the creator's sample-data control is reachable on the unframed page, and
|
||||
`T9.4` still ends with exactly one affordance app-wide.
|
||||
|
||||
---
|
||||
|
||||
## D2 — The QA distribution list is configured in the SOP
|
||||
|
||||
- **Amends:** `CR-014` (`T7.6`)
|
||||
- **Surface:** `server/` + `html/`
|
||||
|
||||
`CR-014` says entering `Ready for QA` "emails the assigned QA representative and the QA/QC
|
||||
members named on the work package". Asked who should receive it, the answer was **the QA
|
||||
group only, and the group is set up once during SOP configuration as a dropdown** — not typed
|
||||
per work package.
|
||||
|
||||
That makes the recipient list SOP configuration, which means a wizard field, which means
|
||||
`T7.6` acquires a dependency on the wave 5 SOP wizard it did not have.
|
||||
|
||||
Rejection routing was also settled: **a rejection notifies the work package owner and the
|
||||
distribution list**, not only the person who submitted it.
|
||||
|
||||
**Replaces the `CR-014` done-when** "entering it sends email to the QA rep and named QA/QC
|
||||
members" with:
|
||||
|
||||
- the QA distribution list is chosen in the SOP wizard from project members
|
||||
- entering `Ready for QA` emails that list and nobody else
|
||||
- rejection emails the work package owner and the same list
|
||||
|
||||
---
|
||||
|
||||
## D3 — The creator stays one page: side navigation plus collapsible sections
|
||||
|
||||
- **Amends:** `F6` (`T7.2`)
|
||||
- **Surface:** `html/`
|
||||
|
||||
`T7.2` as written says "section tabs or an equivalent that shows one coherent group at a
|
||||
time", with the done-when "no single view exceeds roughly two screen heights at 1440px".
|
||||
Asked to choose, the answer was **one long form with navigation down the side** — and then,
|
||||
when the height conflict was raised, the decision was delegated: *"do what you recommend is
|
||||
best to UX."*
|
||||
|
||||
**Recommended and adopted:** one page, persistent side navigation, and each section
|
||||
collapsible with only the current one open by default, plus an `Expand all` control for
|
||||
people who would rather scroll straight through. 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.
|
||||
|
||||
**Replaces the `F6` done-when** "no single view exceeds roughly two screen heights at 1440px"
|
||||
with "no single view exceeds roughly two screen heights at 1440px **at rest**" — that is,
|
||||
with the default collapse state, which is the state the page is actually in when it loads.
|
||||
Expanding everything deliberately is allowed to exceed it.
|
||||
|
||||
**Replaces** "toggled-off sections have no tab" with "toggled-off sections have no entry in
|
||||
the side navigation", and "tabs are keyboard operable and follow the tab pattern with
|
||||
`aria-selected` and arrow keys" with "the side navigation is keyboard operable, marks the
|
||||
current section with `aria-current`, and each section header is a real disclosure button with
|
||||
`aria-expanded`".
|
||||
|
||||
---
|
||||
|
||||
## D4 — Urgent surfaces the audited override; it does not bypass the gate
|
||||
|
||||
- **Amends:** `CR-003` (`T6.2`, shipped) and `A1` (`T7.3`)
|
||||
- **Surface:** `html/`
|
||||
|
||||
Asked whether an `Urgent` package should be issuable while a constraint is still open, the
|
||||
first answer was "maybe, with a constraint active". The concern raised back: silently
|
||||
bypassing the gate would undermine the delay-documentation use case that is the entire
|
||||
business justification for the constraint workflow — a constraint log that can be shown to
|
||||
have been skipped stops supporting a notice of delay. **Answer: yes, surface the audited
|
||||
path instead.**
|
||||
|
||||
So `Urgent` does not create a new bypass. It makes the existing logged-override path —
|
||||
`confirmEarlyRelease()` — prominent on an urgent package, so the release still produces a
|
||||
history entry with who, when and why.
|
||||
|
||||
**Adds to the `T7.3` done-when list:**
|
||||
|
||||
- an `Urgent` package with an open constraint offers the logged override in the primary
|
||||
action position rather than 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
|
||||
|
||||
---
|
||||
|
||||
## D5 — Usage data moves to the admin console
|
||||
|
||||
- **Amends:** `B7` (`T7.1`)
|
||||
- **Surface:** `html/`
|
||||
- **New task:** `T7.10`
|
||||
|
||||
`docs/reference/creator-frame.md` §2b records that five of the nine colliding script globals
|
||||
are usage analytics implemented twice, and that the wizard's `showAnalytics` has no caller
|
||||
because the button lives on the creator. Asked where it belongs now that the creator is a
|
||||
page in its own right, the answer was **the admin console**.
|
||||
|
||||
That deletes one of the two implementations rather than merging them, and takes an
|
||||
operator-facing control off a package-authoring screen.
|
||||
|
||||
**Done when:** analytics is reachable from `admin.html`, no analytics control remains on the
|
||||
creator or the wizard, and only one of the two implementations survives.
|
||||
|
||||
---
|
||||
|
||||
## D6 — The material list uploads at SOP configuration
|
||||
|
||||
- **Amends:** `CR-013` (`T8.5`)
|
||||
- **Surface:** `server/` + `html/`
|
||||
- **New task:** `T8.6`
|
||||
|
||||
`CR-013` is explicit that there is no parts catalog: line items are free text, because
|
||||
Nate's spreadsheet and the master material workbook have not been supplied
|
||||
(`IMPLEMENTATION.md` section 8). Asked whether to wait for them or build the upload path now,
|
||||
the answer was **upload now**.
|
||||
|
||||
This is `CR-005` applied to a second list. The location upload built at `T5.4` — paste or
|
||||
file, validated, rejected rows reported with the source line, editable afterwards — is the
|
||||
pattern to reuse rather than re-invent.
|
||||
|
||||
**This does not open the out-of-scope parts catalog.** Section 7 defers "full material request
|
||||
and inventory system, including the parts catalog and warehouse integration". A project-scoped
|
||||
list uploaded by the project is not a catalog, carries no inventory levels and integrates
|
||||
with nothing. If the diff grows a stock count, it has crossed the line.
|
||||
|
||||
**Done when:** a material list uploads during SOP configuration, `T8.5` line items select
|
||||
from it, free text still works when the list is empty, and no inventory or warehouse field
|
||||
exists in the diff.
|
||||
|
||||
---
|
||||
|
||||
## D7 — Archived projects are readable, by project admins
|
||||
|
||||
- **Amends:** `B3` (`T5.2`, shipped), `C1`
|
||||
- **Surface:** `server/` + `html/`
|
||||
- **New task:** `T9.8`
|
||||
|
||||
Archiving exists for both projects and work packages, and the server already refuses writes
|
||||
to an archived project. What it does not do is show them: an archived project leaves the
|
||||
launcher and there is no way back to it. Asked who should be able to open one, the answer
|
||||
was **project admins only**, arrived at after considering everyone.
|
||||
|
||||
So this is a listing and a read-only render behind a role check, not a new archive
|
||||
mechanism.
|
||||
|
||||
**Done when:** a project admin can list and open archived projects, everything renders
|
||||
read-only, a non-admin sees no archived projects at all, and no write path is reachable from
|
||||
the read-only view.
|
||||
|
||||
---
|
||||
|
||||
## D8 — Upload limits: 5MB a file, 2GB a project, PDFs and images, one database
|
||||
|
||||
- **Amends:** `CR-007` (`T7.7`)
|
||||
- **Surface:** `server/` + `html/`
|
||||
|
||||
Four answers, taken together:
|
||||
|
||||
| Question | Answer |
|
||||
|---|---|
|
||||
| Per-file size limit | 5MB |
|
||||
| Accepted types | PDFs and images |
|
||||
| Where files live | the same database as everything else |
|
||||
| What caches offline | only the work packages assigned to that person |
|
||||
|
||||
The follow-up was the consequence: 5MB files in the same database means every encrypted
|
||||
backup carries them, and a busy project reaches a gigabyte without anyone noticing until a
|
||||
restore is slow. Splitting the files out was **rejected** on the grounds that a backup which
|
||||
excludes the drawings is a backup you cannot restore from. **A per-project ceiling of 2GB was
|
||||
approved instead**, with a warning before it is reached.
|
||||
|
||||
**Adds to the `CR-007` done-when list:**
|
||||
|
||||
- a file over 5MB is refused before upload, with the limit stated
|
||||
- a type outside PDF and image is refused before upload, with the accepted types stated
|
||||
- a project at 80% of 2GB warns, and at 2GB refuses with a message naming the ceiling
|
||||
- the running project total is visible where uploads happen
|
||||
- offline caching covers the requesting user's assigned packages, not the whole project
|
||||
|
||||
---
|
||||
|
||||
## D9 — Ready for QA appears in Field View
|
||||
|
||||
- **Amends:** `CR-014` (`T7.6`)
|
||||
- **Surface:** `html/`
|
||||
|
||||
`CR-014` puts the new state on "a dashboard view or filter". Asked whether the field needs to
|
||||
see it too, the answer was **yes, it shows in field view**.
|
||||
|
||||
**Adds to the `T7.6` done-when list:** Field View shows which packages are in `Ready for QA`,
|
||||
and the state is legible at 390px without colour being the only signal.
|
||||
|
||||
---
|
||||
|
||||
## D10 — Email is switched on and off from the admin console
|
||||
|
||||
- **Amends:** `CR-011` (`T8.3`), `CR-014` (`T7.6`)
|
||||
- **Surface:** `server/` + `html/`
|
||||
|
||||
All new outbound email in this plan ships **gated off** — a standing instruction from the
|
||||
wave 5 kickoff, verified against a capture sink rather than a real mail server. Asked who
|
||||
turns it on, the answer was **the admin controls email**.
|
||||
|
||||
That makes the gate a stored setting with a console control, not an environment variable
|
||||
somebody edits on the server. Existing hardening constraints stand: the SMTP password lives
|
||||
in the environment and nowhere else, and no customer IP appears in an email body.
|
||||
|
||||
**Done when:** the send path is complete and exercised against a capture sink, the default is
|
||||
off, an administrator can turn it on from `admin.html`, a non-administrator cannot, and
|
||||
changing it is written to the audit log.
|
||||
|
||||
---
|
||||
|
||||
## Closed without work
|
||||
|
||||
**Free-text location migration.** Work packages created before `CR-004` recorded their
|
||||
location as typed text, and those values match nothing in the structured list, so they do not
|
||||
roll up. The question was whether somebody should match them by hand or leave them as
|
||||
history. Answer: *"It is just sample data at this point so that is ok."* No migration is
|
||||
built and no item is opened. If this plan ever runs against a database with real
|
||||
pre-`CR-004` packages in it, this decision has to be revisited before `T6.4`'s rollups can be
|
||||
trusted — noted here so that is a decision and not a surprise.
|
||||
|
||||
**The off-palette colours.** `BL-004`, `BL-005`, `BL-008` and `BL-009` were each deferred by
|
||||
their own wave on the same grounds: fixing them changes a rendered colour, and the wave that
|
||||
found them was forbidden to change one. Together they are the help centre's separate
|
||||
52-colour palette, two dialogs styled by inline attributes, a second brand blue and a ninth
|
||||
amber. Asked whether to unify them or leave them, the answer was **change them**. They stay
|
||||
in wave 9 under `C4`, but they are now approved work rather than four open questions.
|
||||
|
||||
---
|
||||
|
||||
## What this changes in the wave table
|
||||
|
||||
| Wave | Was | Now also |
|
||||
|---|---|---|
|
||||
| 7 | `B7` `A1` `CR-015` `A2` `A6` `CR-014` `CR-007` `B6` `S1`(creator) `F6` | `D1` `D2` `D3` `D4` `D5` `D8` `D9` `D10`(half) |
|
||||
| 8 | `CR-009` `CR-010` `CR-011` `CR-012` `CR-013` | `D6` `D10`(half) |
|
||||
| 9 | `CR-008` `CR-017` `S6` `S7` `C1` `C2` `C4` | `D7`, and `C4` now carries the four approved colour items |
|
||||
|
||||
Three new tasks — `T7.10`, `T8.6` and `T9.8`. Everything else is an amended criterion on a
|
||||
task that already existed.
|
||||
@@ -1,20 +1,29 @@
|
||||
# Wave 7 — The creator
|
||||
|
||||
**Items:** `B7`, `A1`, `CR-015`, `A2`, `A6`, `CR-014`, `CR-007`, `B6`, `S1` (creator), `F6`
|
||||
**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.
|
||||
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`
|
||||
- **Items:** `B7`, `D1`
|
||||
- **Depends on:** T6.5
|
||||
- **Blocks:** T7.2 through T7.9
|
||||
- **Blocks:** T7.2 through T7.10
|
||||
- **Surface:** `html/`
|
||||
- **Files:** parent page hosting the creator, the creator itself, cross-frame messaging
|
||||
|
||||
@@ -32,6 +41,28 @@ 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
|
||||
@@ -40,12 +71,16 @@ behind a flag.
|
||||
- [ ] `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 + A4 pattern: Section tabs replace the 4,700px form
|
||||
### T7.2 — F6 + D3: Side navigation and collapsible sections replace the 4,700px form
|
||||
|
||||
- **Items:** `F6`
|
||||
- **Items:** `F6`, `D3`
|
||||
- **Depends on:** T7.1, T5.5, T3.5
|
||||
- **Blocks:** T7.9
|
||||
- **Surface:** `html/`
|
||||
@@ -58,24 +93,41 @@ jump links standing in for structure.
|
||||
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
|
||||
- [ ] toggled-off sections have no tab
|
||||
- [ ] 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
|
||||
- [ ] tabs are keyboard operable and follow the tab pattern with `aria-selected` and arrow keys
|
||||
- [ ] 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`
|
||||
- **Items:** `A1`, `CR-015`, `D4`
|
||||
- **Depends on:** T7.1
|
||||
- **Blocks:** T7.4, T7.6
|
||||
- **Surface:** `server/` + `html/`
|
||||
- **Files:** status handling, constraint handling, `wp-creation-app.js:1962-1972`
|
||||
- **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
|
||||
@@ -85,9 +137,15 @@ in front of the Micron team.
|
||||
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 — `wp-creation-app.js:1962-1972`
|
||||
contains a deliberate logged-override path for predecessors, and Issue (Hold) is a branch
|
||||
from several states, not a single linear step.
|
||||
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
|
||||
@@ -107,6 +165,17 @@ the symptom by recalculating on page load only.
|
||||
- [ ] 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.
|
||||
@@ -161,8 +230,8 @@ They open it on a phone and need the answer without scrolling or clicking.
|
||||
|
||||
### T7.6 — CR-014: Ready for QA gate
|
||||
|
||||
- **Items:** `CR-014`
|
||||
- **Depends on:** T7.3, T4.2 (blocking dependency `X1`)
|
||||
- **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
|
||||
@@ -183,15 +252,35 @@ 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
|
||||
- [ ] entering it sends email to the QA rep and named QA/QC members
|
||||
- [ ] 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.
|
||||
@@ -200,7 +289,7 @@ CxAlloy. Integration with CxAlloy is explicitly out of scope. This gate is notif
|
||||
|
||||
### T7.7 — CR-007: Upload drawings for offline access
|
||||
|
||||
- **Items:** `CR-007`
|
||||
- **Items:** `CR-007`, `D8`
|
||||
- **Depends on:** T7.2, T4.3 (blocking dependency `X8`)
|
||||
- **Blocks:** nothing
|
||||
- **Surface:** `server/` + `html/`
|
||||
@@ -221,14 +310,31 @@ Show file size limits and supported types in the UI before upload, not after fai
|
||||
**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
|
||||
|
||||
@@ -287,11 +393,47 @@ errors is marked. Remove the creator's native dialogs.
|
||||
|
||||
---
|
||||
|
||||
### 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
|
||||
|
||||
- [ ] no iframe; `F4` resolved structurally
|
||||
- [ ] `CR-015` fixed with a regression test and a stated root cause
|
||||
- [ ] hold state is derived, and history records every transition
|
||||
- [ ] the QA gate emails a working deep link
|
||||
- [ ] drawings upload and open offline on a tablet
|
||||
- [ ] the QA gate emails a working deep link, to the SOP-configured list, with the gate off by default
|
||||
- [ ] drawings upload and open offline on a tablet, inside the 5MB and 2GB limits
|
||||
- [ ] creator native dialog count is 0
|
||||
- [ ] the creator is a page: app bar, side navigation, collapsible sections, focus rings, at rest under two screen heights
|
||||
- [ ] `D1` through `D5`, `D8`, `D9` and `D10` are each satisfied or explicitly carried with a reason
|
||||
- [ ] no real email left this branch; the capture sink count is recorded
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
# Wave 8 — Kitting and material
|
||||
|
||||
**Items:** `CR-009`, `CR-010`, `CR-011`, `CR-012`, `CR-013`
|
||||
**Items:** `CR-009`, `CR-010`, `CR-011`, `CR-012`, `CR-013`, and from August 18: `D6`, `D10`
|
||||
**Depends on:** wave 7 merged
|
||||
|
||||
**Build order is not task order.** `T8.6` is numbered last because it was added on August 18,
|
||||
but it **blocks `T8.5`** - the request cannot select from a list that does not exist yet. Build
|
||||
`T8.1`, `T8.2`, `T8.3`, `T8.4`, `T8.6`, then `T8.5`. Task IDs are referenced outside this repo
|
||||
and are not renumbered to make the order read left to right.
|
||||
**Decision, approved Aug 14 2026:** keep and extend Kitting, then ship it **toggled off** for
|
||||
the Micron EUV SOP. Kitting is not happening at Micron today — it is complicated by
|
||||
journeyman ratio and warehouse cost — but the team expects to get there, and prefab arguably
|
||||
@@ -59,12 +64,17 @@ everything assigned to them.
|
||||
- [ ] the dashboard filters by warehouse owner
|
||||
- [ ] removing someone from the project does not break existing work packages referencing them
|
||||
|
||||
**Confirmed August 18.** Asked whether the warehouse owner belongs to the project or to each
|
||||
work package, the answer was **on the work package**. A project default is fine as a
|
||||
convenience, but the field that notifications read is the one on the package, so a package
|
||||
retargeted to a different warehouse notifies the right person without touching the project.
|
||||
|
||||
---
|
||||
|
||||
### T8.3 — CR-011: Kitting status change notification
|
||||
|
||||
- **Items:** `CR-011`
|
||||
- **Depends on:** T8.2, T4.2 (blocking dependency `X1`)
|
||||
- **Items:** `CR-011`, `D10`
|
||||
- **Depends on:** T8.2, T7.6 (the email gate), T4.2 (blocking dependency `X1`)
|
||||
- **Blocks:** nothing
|
||||
- **Surface:** `server/` + `html/`
|
||||
- **Files:** notification service, kitting status handling
|
||||
@@ -87,6 +97,8 @@ convention, not two.
|
||||
- [ ] formatting and tone match the existing status-change email
|
||||
- [ ] rapid consecutive changes do not produce a burst of near-identical emails
|
||||
- [ ] send failures are logged and surfaced
|
||||
- [ ] the gate built at `T7.6` is reused, not re-implemented; kitting email is off by default and turned on from `admin.html` (`D10`)
|
||||
- [ ] the send path is exercised against a capture sink with the captured count asserted; no real mail leaves this branch
|
||||
|
||||
---
|
||||
|
||||
@@ -118,8 +130,8 @@ printout.
|
||||
|
||||
### T8.5 — CR-013: Lightweight material request
|
||||
|
||||
- **Items:** `CR-013`
|
||||
- **Depends on:** T8.4, T7.2 (sequencing dependency `X6`)
|
||||
- **Items:** `CR-013`, `D6`
|
||||
- **Depends on:** T8.4, T8.6, T7.2 (sequencing dependency `X6`)
|
||||
- **Blocks:** nothing
|
||||
- **Surface:** `server/` + `html/`
|
||||
- **Files:** Materials section, request model, dashboard
|
||||
@@ -145,20 +157,72 @@ delivery location and status.
|
||||
card on a 4,700px form. And do not invent a parts list — Nate's spreadsheet and the master
|
||||
material workbook have not been supplied yet (see `IMPLEMENTATION.md` section 8).
|
||||
|
||||
**Amended August 18 (`D6`).** Two answers change this task. Line items **select from a
|
||||
project material list uploaded during SOP configuration** (`T8.6`) rather than being typed
|
||||
from nothing - and free text still works when no list has been loaded, which is the state
|
||||
every project is in today. And submitting a request **notifies the warehouse owner named on
|
||||
the work package** (`CR-010`), which is the routing that replaces the informal funnel through
|
||||
one person.
|
||||
|
||||
`D6` does not open the deferred parts catalog. A project-scoped list the project uploaded is
|
||||
not a catalog: no inventory levels, no warehouse integration, no shared master data. If a
|
||||
stock count appears in the diff, it has crossed the line `IMPLEMENTATION.md` section 7 draws.
|
||||
|
||||
**Done when:**
|
||||
|
||||
- [ ] line items can be added, edited and removed, with quantity and unit
|
||||
- [ ] line items select from the `T8.6` list when one exists, and accept free text when it does not
|
||||
- [ ] needed-by date, requestor, delivery location and status all persist
|
||||
- [ ] requests appear on the dashboard, filterable by location and status
|
||||
- [ ] submitting a request notifies the warehouse owner named on the work package
|
||||
- [ ] no parts catalog, inventory count or warehouse integration exists in the diff
|
||||
- [ ] the section respects `CR-006` toggles
|
||||
- [ ] the whole flow works at 390px, since requests originate in the field
|
||||
|
||||
---
|
||||
|
||||
### T8.6 — D6: Upload the material list at SOP configuration
|
||||
|
||||
- **Items:** `D6`
|
||||
- **Depends on:** T8.1
|
||||
- **Blocks:** T8.5
|
||||
- **Surface:** `server/` + `html/`
|
||||
- **Files:** SOP wizard, material list model and routes, `T5.4`'s upload component
|
||||
|
||||
**Intent:** `CR-013` was written to accept free text because Nate's spreadsheet and the master
|
||||
material workbook had not been supplied, and they still have not been. Asked on August 18
|
||||
whether to wait for them, the answer was **build the upload path now**, the same call that was
|
||||
made for the location list at `CR-005`.
|
||||
|
||||
**Do:** Reuse `T5.4`. The location upload already does paste-or-file, validates, reports
|
||||
rejected rows with the source line number, and stays editable afterwards. Build the material
|
||||
list the same way and against the same component, not beside it.
|
||||
|
||||
Keep the field set small and obvious: description, unit, and an optional code. That is what
|
||||
`T8.5` needs to populate a line item.
|
||||
|
||||
**Do not:** add inventory levels, stock counts, pricing or a warehouse identifier. Do not make
|
||||
the list mandatory - a project with no list must still be able to raise a request. Do not
|
||||
hardcode sample part numbers; seed with an obviously-fake sample as `CR-005` does.
|
||||
|
||||
**Done when:**
|
||||
|
||||
- [ ] a material list uploads or pastes during SOP configuration and persists per project
|
||||
- [ ] rejected rows are reported with the source line and a reason
|
||||
- [ ] the list is editable after upload, and entries can be deactivated rather than deleted
|
||||
- [ ] `T8.5` line items select from it
|
||||
- [ ] a project with no list can still raise a request with free text
|
||||
- [ ] the upload component is the `T5.4` one; grep confirms there is not a second implementation
|
||||
- [ ] no inventory, pricing or stock field exists in the diff
|
||||
- [ ] the flow works at 390px
|
||||
|
||||
---
|
||||
|
||||
## Wave 8 exit criteria
|
||||
|
||||
- [ ] Kitting is fully built and toggled off for Micron EUV
|
||||
- [ ] notifications carry working deep links and a delivery location
|
||||
- [ ] notifications carry working deep links and a delivery location, and are off by default
|
||||
- [ ] the material request is the lightweight scope, nothing more
|
||||
- [ ] a material list uploads at SOP configuration and feeds the request (`D6`)
|
||||
- [ ] no guessed part numbers or floor names anywhere in the code
|
||||
- [ ] no real email left this branch; the capture sink count is recorded
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
# Wave 9 — Verification and cleanup
|
||||
|
||||
**Items:** `CR-008`, `CR-017` (guard), `S6`, `S7`, `S8`, `C1` audit, `C2` audit, part of `C4`
|
||||
**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.
|
||||
@@ -117,6 +123,11 @@ sample project only.
|
||||
- [ ] 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
|
||||
@@ -128,9 +139,15 @@ sample project only.
|
||||
- **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. 15 `.help-tip` badges are `<span>` elements with no
|
||||
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.
|
||||
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`.
|
||||
@@ -140,7 +157,7 @@ Compare against the wave 0 baseline counts:
|
||||
| Metric | Baseline | Target |
|
||||
|---|---|---|
|
||||
| `<div>` / `<span>` with `onclick` | 12 / 2 | 0 |
|
||||
| `.help-tip` unreachable by keyboard | 15 | 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 |
|
||||
@@ -159,7 +176,7 @@ Compare against the wave 0 baseline counts:
|
||||
|
||||
- **Items:** `C2`
|
||||
- **Depends on:** T9.5
|
||||
- **Blocks:** nothing
|
||||
- **Blocks:** T9.8
|
||||
- **Surface:** `html/`
|
||||
- **Files:** all pages
|
||||
|
||||
@@ -180,15 +197,95 @@ after screenshots and compare against the wave 0 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.6
|
||||
- **Depends on:** T9.8, T9.9
|
||||
- **Blocks:** nothing
|
||||
- **Surface:** documentation
|
||||
- **Files:** creates `docs/reference/completion.md`
|
||||
|
||||
**Do:** Walk all 55 items from `IMPLEMENTATION.md` section 6 and record, for each: built /
|
||||
**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.
|
||||
|
||||
@@ -200,7 +297,7 @@ criteria turned out wrong, inputs still outstanding, and follow-ups logged along
|
||||
|
||||
**Done when:**
|
||||
|
||||
- [ ] all 55 items are accounted for with a PR reference or a stated reason
|
||||
- [ ] 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
|
||||
@@ -214,4 +311,6 @@ criteria turned out wrong, inputs still outstanding, and follow-ups logged along
|
||||
- [ ] one icon system, one sample-data affordance
|
||||
- [ ] accessibility metrics hit target or are documented
|
||||
- [ ] the primary flow works at 390px
|
||||
- [ ] every item is reconciled
|
||||
- [ ] archived projects are readable by project admins and invisible to everyone else (`D7`)
|
||||
- [ ] the backlog has no entry still pointing at wave 9
|
||||
- [ ] every item is reconciled - all 65
|
||||
|
||||
Reference in New Issue
Block a user