Six of six exit criteria verified and ticked. Wave totals: 6 tasks (T8.1-T8.6), 3 new probe suites + 1 extended (kitting 26, kitting_notify 17, materials 17, mreq 19 - 79 new checks), one Alembic migration (material_items), one shared component extracted (wp-list-import.js), no real email sent anywhere on this branch. Items: CR-009, CR-010, CR-011, CR-012, CR-013, D6, D10 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
229 lines
11 KiB
Markdown
229 lines
11 KiB
Markdown
# 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)
|