Wiki · Workflow companion

New assembly item (spec → BOM → NS)

A new assembly product enters the system. The 16-step cascade handles spec intake, allergen validation, BOM definition, NS item + BOM record creation, spec sheet PDF generation, pricing pipeline registration, and customer notification for shared-brand customers.

Stub · Contract present, runner stub-only
What this is

New assembly item (spec → BOM → NS)

New assembly item creation is the longest cascade on the platform. A new product introduces fifteen-plus downstream effects: catalog rows, BOM rollup, NS records, a PDF spec sheet, pricing pipeline registration, brand routing, bid eligibility, customer programs that should price it, and notifications to customers within the shared brand line.

Each step has a precondition or conditional. The workflow gate (Mike's approval) sits after spec parsing and BOM definition but before any write — once approved, the cascade is deterministic.

Risk level 4 (high). A bad spec going live could ripple into bids, quotes, and customer-facing pages. The 4-stage HITL gates (allergen validation, BOM completeness, spec sheet review, customer notification) exist precisely for that reason.

When to use it

Trigger conditions

Heuristic

The precondition bom_complete_if_assembly blocks on an empty BOM for any assembly item. This catches the most common new-item mistake: shipping the spec without the BOM and discovering the cost basis is missing only after the first invoice.

Step-by-step what happens

The 8 beats

  1. 01

    Write spec_items + spec_versions

    INSERT into spec_items (the live spec) and spec_versions (the audit trail, with changed_field=created, new_value=full_json).

    Writes spec_items, spec_versions
    Time ~120ms
    Kind d1_write
    Status stub
  2. 02

    Write items shell

    INSERT into items with the basic shell (itemid, isinactive=F). NS will populate the rest after push. Parallel with write_spec_items.

    Writes items
    Time ~80ms
    Kind d1_write
    Status stub
  3. 03

    Recompute assembly cost rollup (conditional)

    If is_assembly, call recompute_assembly_cost_rollup to compute raw + packaging + labor + overhead + freight from the BOM components.

    Writes assembly_cost_rollup
    Time ~300ms
    Kind chat_tool
    Status stub
    Note conditional · is_assembly
  4. 04

    NS item record

    Enqueue a NS push to create the item record via customscript_gfs_platform_query RESTlet. The NS record is the system of record; this push is load-bearing.

    Writes NetSuite item record
    Time ~3–8s
    Kind ns_push
    Status stub
    Note retry · 2 attempts linear backoff
  5. 05

    NS BOM record (conditional)

    If is_assembly, enqueue a NS BOM push with the components and quantities.

    Writes NetSuite BOM record
    Time ~3–8s
    Kind ns_push
    Status stub
    Note conditional · is_assembly
  6. 06

    Generate spec sheet PDF

    POST /api/spec/generate renders the spec sheet template via Browser Rendering and stores at specs/{item_code}.pdf in R2.

    Writes R2 bucket specs/
    Time ~6–10s
    Kind http_call
    Status stub
  7. 07

    Pricing pipeline registration

    INSERT into pricing_master for every customer program that should price this new item. Source-tagged so downstream knows it came from new-item creation.

    Writes pricing_master
    Time ~200ms per N programs
    Kind d1_write
    Status stub
  8. 08

    Customer notification (conditional)

    If shared_brand_customers is non-empty, draft a notification email per customer in the shared brand. Mike approves before send.

    Writes outbound_email_log
    Time ~80ms per customer
    Kind hitl_email_draft
    Status stub
    Note conditional · shared brand customers > 0
Outcomes

What's different after the workflow runs

Spec persisted
D1 + version
≤ 5s
NS records
1–2 created
≤ 15 min
Spec PDF
R2 versioned
≤ 60s
Pricing seeded
Per program
eligibility-matched
Failure modes

What can go wrong and how to recover

Item code not unique

Precondition item_code_unique blocks via UPC + existing-spec check. Mike either picks a new code or runs item_record_review to update the existing item.

BOM missing for assembly

Precondition bom_complete_if_assembly blocks. Mike fills the BOM in the intake form and re-stages.

Allergens missing

Precondition warns (not blocks). Mike confirms and proceeds, or fills allergens before approval. Often happens for ingredient items where allergens are sourced from the vendor spec.

NS push fails

Retry policy is 2 linear-backoff attempts. Persistent failures alert Mike; D1 holds the proposed state and manual POST /admin/ns-push/retry?action_id=<id> recovers.

Related

Adjacent workflows + diagrams

For developers

Code paths + invariants

ConcernWhere
Workflow contractworkflow_definitions WHERE workflow_type='new_assembly_item'
HITL gatesspec intake, BOM completeness, spec review, customer notify
NS RESTletcustomscript_gfs_platform_query
Spec generator endpoint/api/spec/generate
Knowledge reindexqueue: catalog/reindex
Reflexion tagnew_spec,brand:<brand>,category:<cat>
Risk level4
Expected duration~60 min
Triggermanual · sources=spec_sheet_upload, intake_form
// Eligibility match — pricing_master seeding await db.run( "INSERT INTO pricing_master (customer_id, item_code, school_year, source) " + "SELECT customer_id, ?1, school_year, 'new_item_' || ?1 " + "FROM customer_programs WHERE brand=?2 AND status='active'", [item_code, brand] );
Changelog

Dated trail · spot stale claims

Dated trail of when this doc was last touched, what changed, and what to look at if it feels stale.

DateRoundChangeTouched by
2026-05-26R586Added CHANGELOG · SCHEMA · RUNBOOK · BACKLOG sections — wiki became best-in-class operating documentation.Mike + Claude
2026-05-25R584/R585Wiki originally shipped — 8-section structure (hero / what / when / steps / outcomes / failure-modes / related / for-developers).Mike + Claude
If today is more than 60 days past the latest changelog row, treat live system behavior as the source of truth. The doc may have drifted — verify against the workflow contract in workflow_definitions WHERE workflow_type='new_assembly_item' before acting on these claims.
Schema · data contract

The machine-readable spec

Canonical fields, table names, endpoint signatures. What code should match, what tests should assert. workflow_type · new_assembly_item · risk_level · 3.

Inputs (required + optional)

FieldTypeDescription
assembly_namestringDisplay name. Required.
bom_itemsjsonArray of {component_item_id, qty}. Required.
yield_qtydecimalOutput qty per build. Required.
categorystringProduct category.

D1 tables written

TableOperationTrigger
proposed_actionsINSERTAssembly creation proposal
itemsINSERT (post-HITL)NS-mirrored item record
bomINSERT (post-HITL)Per-component BOM rows
ns_pending_pushesINSERTAssembly creation in NS

Endpoints called

MethodPathPurpose
POST/api/workflow/executeRunner entrypoint
POST/api/proposed-actions/:id/decideHITL approval

Events fired

event_typeWhenSubscribers
assembly.createdPost-HITL + NS pushknowledge_corpus rebuild candidate
Runbook · when it breaks

It broke at 2am — what now

Different from "how do I use this." This is the page Mike pulls up when something is wrong: logs to check, recovery steps, who to escalate to.

Scenario · Assembly created in D1 but not in NS

ns_push stub or failed.

  1. Check ns_pending_pushes: SELECT * FROM ns_pending_pushes WHERE entity_ref='assembly:<name>'
  2. Manual create: Create in NS, then update D1 items.ns_internal_id.

Scenario · BOM components don't exist as items in NS

BOM references items that aren't synced.

  1. Verify components: SELECT id FROM items WHERE id IN (<component_ids>)
  2. Sync first: Force a sync of items before assembly creation.

Scenario · Assembly yield wrong

yield_qty was misentered.

  1. Fix in D1: UPDATE items SET yield_qty=? WHERE id=?
  2. Push correction to NS: Via ns_pending_pushes.

Logs to check

Kill switch · emergency stop

If this workflow is misbehaving in a high-impact way (creating bad proposed_actions in volume, pushing wrong things to NS), flip a kill switch:

See kill-switches-state-machine.html for the full state machine + recovery procedure.

Escalation

Primary: Mike Levine (single-admin) · mikelevine@globalfoodsolutions.co. For prolonged outage during business hours, notify warehouse lead + accounting lead so they can defer dependent work.

Backlog · open questions

What's not done · what's uncertain

What's not done, what's uncertain, what we punted. Captured so it survives context switches and doesn't die in someone's head.