# Wave 8 — Kitting and material **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 already qualifies. That means this wave builds functionality that will not be visible on the pilot project. That is intentional. Do not shortcut it on the grounds that nobody is using it, and do not switch it on for Micron. --- ### T8.1 — CR-009: Kitting section retained and structured - **Items:** `CR-009` - **Depends on:** T7.9 - **Blocks:** T8.2, T8.3, T8.4 - **Surface:** `server/` + `html/` - **Files:** Kitting section, SOP configuration **Do:** Confirm the Kitting section is intact and structured to receive `T8.2` through `T8.4`. Define kitting statuses explicitly. Proposed set, adjust only with a stated reason: `Not Started`, `Picking`, `Staged`, `In Transit`, `Delivered`. Then set the section off for the Micron EUV SOP via the `CR-006` toggles. **Done when:** - [ ] kitting statuses are defined as an explicit set, not free text - [ ] the section is off for Micron EUV and absent from its form, detail view and export - [ ] a different SOP can enable it and it works fully - [ ] no kitting data is deleted anywhere --- ### T8.2 — CR-010: Warehouse Owner dropdown - **Items:** `CR-010` - **Depends on:** T8.1 - **Blocks:** T8.3 - **Surface:** `server/` + `html/` - **Files:** Kitting section, dashboard filters **Intent:** A named person owns fulfillment of the kit. Today that is Paul Coonrod and everything bottlenecks through him informally, so the work package should record it explicitly. **Do:** A Warehouse Owner dropdown populated from project members. That person receives kitting notifications by default. Filterable on the dashboard so a warehouse owner can see everything assigned to them. **Done when:** - [ ] the dropdown lists project members and persists a selection - [ ] the selected owner is a default recipient for `T8.3` notifications - [ ] 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`, `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 **Intent:** Extends the existing status-change notification pattern to kitting so the field knows when material moves from requested to staged to delivered without chasing it in Teams. **Do:** A kitting status change emails the work package distribution list. The email states the work package, the old and new status, who changed it, the delivery location, and a direct link to the work package. Match the existing status-change email pattern so users see one convention, not two. **Do not:** send a link to the app root (`X1`). **Done when:** - [ ] every kitting status change sends to the distribution list - [ ] the email includes old status, new status, actor, delivery location and a working deep link - [ ] the link opens that specific work package, including via login for a signed-out recipient - [ ] 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 --- ### T8.4 — CR-012: Delivery location on Kitting / Material - **Items:** `CR-012` - **Depends on:** T8.1, T6.3 - **Blocks:** nothing - **Surface:** `server/` + `html/` - **Files:** Kitting section, print/pick output **Intent:** Delivery logistics are the real pain. Staging at the warehouse, getting it on a truck, then making sure material reaches the correct floor lay-down, shark cage or conduit tree rather than being picked at will by whoever is closest. **Do:** Capture delivery location using the same Building / Floor / Sector lists as `CR-004`, plus a free-text detail field for specifics like lay-down area, shark cage or conduit tree. Include the delivery location on the kitting notification email and on any pick or delivery printout. **Done when:** - [ ] delivery location uses the shared location lists, not a parallel free-text field - [ ] the detail field persists and prints - [ ] the location appears on the `T8.3` email - [ ] it appears on any pick or delivery printout --- ### T8.5 — CR-013: Lightweight material request - **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 **Decision, approved Aug 14 2026:** build the lightweight version. Defer the parts catalog, live inventory and warehouse integration. **Intent:** Material requests run today through per-floor Teams chats and a spreadsheet, all funneling to Paul Coonrod. The comparison drawn in the meeting was a project where requests went into a OneNote and became, in the words used at the time, word vomit. The point of this item is structure, not features. **In scope:** line items (description, quantity, unit), needed-by date, requestor, delivery location (reuse `T8.4`), and status. **Out of scope, do not build:** master parts catalog dropdown, live inventory levels, warehouse system integration. **Do:** Build the in-scope set. Requests are visible on the dashboard and filterable by delivery location and status. **Do not:** build this before `T7.2`. A material card added to the pre-tab creator is a 12th 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 - [x] Kitting is fully built and toggled off for Micron EUV (`kitting_check.py`: the five statuses, the account-backed owner, the delivery trio, the CR-006 toggle on both samples, nothing deleted) - [x] notifications carry working deep links and a delivery location, and are off by default (`kitting_notify_check.py` against the sink; the coalescer keeps bursts to one mail per recipient) - [x] the material request is the lightweight scope, nothing more (`mreq_check.py` greps for catalog/inventory/warehouse and finds none) - [x] a material list uploads at SOP configuration and feeds the request (`D6` - `materials_check.py`; the T5.4 component extracted to `wp-list-import.js`, one implementation for both lists) - [x] no guessed part numbers or floor names anywhere in the code (every seeded value is `Sample …` / `SAMPLE-…`; `locations_check.py` still sweeps the tree for the unspecified B100 names) - [x] no real email left this branch; the capture sink count is recorded (every send in `kitting_notify_check.py` and `mreq_check.py` terminates at the in-process sink; counts and recipients asserted)