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>
11 KiB
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.3notifications - 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.6is reused, not re-implemented; kitting email is off by default and turned on fromadmin.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.3email - 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.6list 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-006toggles - 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.5line items select from it- a project with no list can still raise a request with free text
- the upload component is the
T5.4one; 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 (
kitting_check.py: the five statuses, the account-backed owner, the delivery trio, the CR-006 toggle on both samples, nothing deleted) - notifications carry working deep links and a delivery location, and are off by default (
kitting_notify_check.pyagainst the sink; the coalescer keeps bursts to one mail per recipient) - the material request is the lightweight scope, nothing more (
mreq_check.pygreps for catalog/inventory/warehouse and finds none) - a material list uploads at SOP configuration and feeds the request (
D6-materials_check.py; the T5.4 component extracted towp-list-import.js, one implementation for both lists) - no guessed part numbers or floor names anywhere in the code (every seeded value is
Sample …/SAMPLE-…;locations_check.pystill sweeps the tree for the unspecified B100 names) - no real email left this branch; the capture sink count is recorded (every send in
kitting_notify_check.pyandmreq_check.pyterminates at the in-process sink; counts and recipients asserted)