Wiki · Workflow companion

Assembly build + BOM review

The catalog-cleanup workhorse for assemblies. Review the current BOM + cost rollup + customer-program usage, propose line-level changes, and after Mike's tap push back to NS, recompute every downstream rollup, regenerate the spec sheet, and bust dependent caches.

Mixed · Some steps live, others stubbed
What this is

Assembly build + BOM review

Assembly build review is the assembly-side counterpart to item_record_review. Where the item review keeps the items catalog clean, this one keeps assemblies — the BOM-bearing parents — honest. Mike (or the weekly cost-drift cron) opens an assembly, sees its full state, and proposes targeted BOM line changes or header field updates.

The cascade is deliberately wide: BOM changes ripple to assembly_cost_rollup, then to pricing_master for any active customer pricing, then to bid_lines for any open bid, then to the spec sheet PDF, then to KV caches that key off the assembly_id.

Risk level 3 (medium). Contract stored as workflow_definitions WHERE workflow_type='assembly_build_review'.

When to use it

Trigger conditions

Heuristic

If any BOM line references a USDA commodity item, step 9 also kicks off usda_drawdown_commit automatically — that ensures the commodity allocation stays in sync without Mike chasing it.

Step-by-step what happens

The 9 beats

  1. 01

    Stage assembly header update (if header_changes)

    Header field changes (description, custitem_brand, custitem_pack_size, custitem_case_count, custitem_yield) stage as one proposed_actions row with action_type=assembly_header_update.

    Writes proposed_actions
    Time ~80ms
    Kind stage_proposed_action
    Status real
    Note conditional · header_changes present
  2. 02

    Stage BOM line updates (if line_changes)

    Each BOM line add/update/remove stages as one (or batched) proposed_actions row with action_type=assembly_bom_update. Cascade policy determines bundling.

    Writes proposed_actions
    Time ~80ms per line
    Kind stage_proposed_action
    Status real
    Note conditional · line_changes present
  3. 03

    Invalidate assembly cache

    Keys assembly:{assembly_code}, assembly_full:{assembly_id}, and bom:{assembly_id} are deleted so the next /assembly/<code> render is fresh.

    Writes HUB_CACHE KV
    Time ~40ms
    Kind kv_invalidate
    Status real
  4. 04

    Recompute cost rollup

    If BOM lines changed, assembly_cost_rollup recomputes raw + packaging + labor + overhead + freight from the new BOM. Persists drift_pct_vs_prior for next cron.

    Writes assembly_cost_rollup
    Time ~200ms
    Kind d1_write
    Status stub
    Note conditional · line_changes present
  5. 05

    Invalidate pricing cache for affected rows

    Each (customer, school_year) pricing cache that touched this assembly gets busted. Keys derive from context.active_pricing_rows.

    Writes HUB_CACHE KV
    Time ~40ms per key
    Kind kv_invalidate
    Status real
  6. 06

    Regenerate spec sheet (conditional)

    If header_changes touched pack_size or case_count, or if line_changes affected yield, the spec sheet PDF regenerates via the existing regenerate_spec_sheet tool.

    Writes R2 bucket specs/
    Time ~6s
    Kind chat_tool
    Status stub
    Note conditional · spec-relevant fields
  7. 07

    Flag dependent bids

    For any open bid_line whose item_code equals the assembly's item_code (status in active or submitted), a flag marks the bid for re-pricing review.

    Writes bid_lines flag column
    Time ~50ms
    Kind flag
    Status stub
  8. 08

    Notify program owners (conditional)

    If customer_programs_using is non-empty, one email per customer with this assembly drafts in outbound_email_log with status=pending_review.

    Writes outbound_email_log
    Time ~80ms per customer
    Kind hitl_email_draft
    Status stub
    Note conditional · customer_programs_using present
  9. 09

    Trigger USDA drawdown check (conditional)

    If a BOM line references a USDA commodity item, the runner invokes usda_drawdown_commit so allocation stays aligned with the new BOM.

    Writes workflow_run_log + usda tables
    Time ~30 min downstream
    Kind workflow_class_invoke
    Status stub
    Note conditional · USDA component
Outcomes

What's different after the workflow runs

BOM lines
Updated
NS via HITL
Cost rollup
Recomputed
≤ 200ms after approval
Spec sheet
Regenerated
R2 versioned
Caches
Busted
~40ms each
Failure modes

What can go wrong and how to recover

Cost rollup compute fails

Retry policy is 2 attempts with backoff. Final failure raises an anomaly; manual recovery is POST /admin/assembly/recompute?assembly_id=<id>.

NS push transient (network)

Retry policy applies. Drainer cron re-attempts within 15 min. D1 holds the proposed state.

BOM line references a deleted item

Precondition catches this before stage; the runner refuses with a block-severity error. Mike fixes the line_key in the proposed payload and re-stages.

Spec sheet regen times out

Browser Rendering can stretch on large BOMs. Old PDF remains in R2; next manual regen catches it.

Related

Adjacent workflows + diagrams

For developers

Code paths + invariants

ConcernWhere
Workflow contractworkflow_definitions WHERE workflow_type='assembly_build_review'
Drift detectorR533 weekly assembly rollup cron
Cost rollup tableassembly_cost_rollup
Spec regen toolregenerate_spec_sheet (executeChatTool branch)
USDA triggerany BOM line where line_key matches usda_commodity_items
Reflexion tagassembly_review,bom_change,data_cleanup
Risk level3
Expected duration~variable (data-driven)
Triggermanual_or_event · event_type_glob=assembly.cost_drift_detected
// Conditional USDA trigger — step 9 if (bomLines.some(l => usdaItems.has(l.line_key))) { await runner.invoke('usda_drawdown_commit', { assembly_id }); } // Cost rollup drift threshold (R533) if (drift_pct > DRIFT_THRESHOLD_PCT) emit('assembly.cost_drift_detected');