Assembly build request risk 2 · lowmanual_or_eventreflexion on

workflow_type: assembly_build_request · owner: mike · contract v2 · source diagram: ns-assembly-build-flow.html

Caller requests an assembly build (chat tool, scheduled production plan, or fulfillment shortfall). Cascade: BOM resolve + component availability + cost rollup snapshot + HITL approve + NS assemblybuild push + inventory recompute + cost variance flag + downstream quote refresh.

0 · Visual flow Assembly build request — 10 fan-out targets, 3 verify checks

idle
NS assembly build flow — build request → BOM resolution → cost rollup → capacity check → HITL → component consumption → build operation → assembly created → spec sheet refresh → cost recalc 01 / Request 02 / BOM 03 / Rollup 04 / Capacity 05 / HITL 06 / Consume 07 / Build 08 / Created 09 / Spec 10 / Recalc BUILD REQUEST — Operator, WO, or sales-driven request to produce N units of an assembly. Source can be manual, an open work order, or a customer order requiring assembled stock. TRIGGER manual: NS UI · production form wo_driven: parent workorder release so_driven: sales_order needs FG TABLES read: assemblies (master) STATUS: REAL build request assembly_id + qty source: manual/WO/SO FRONTEND · NS UI i BOM RESOLUTION — Pull current assembly_bom rows for assembly_id. Validate every line_key exists in items master, has a current cost, and has on-hand availability. ACTION resolve: assembly_bom WHERE assembly_id=? validate: line_key IN items scale: qty × bom_qty per line TABLES read: assembly_bom · items STATUS: REAL BOM resolution assembly_bom rows scale by qty DATABASE · D1 i COST ROLLUP — Refresh assembly_cost_rollup by summing raw component cost, packaging, labor estimate, overhead allocation, and freight per pillar 4 cost-surface logic. COMPONENTS raw_cost: sum(bom.qty × component.cost) packaging: from bom packaging lines labor: bom.labor_min × labor_rate overhead: pct allocation freight: per-location adder TABLES write: assembly_cost_rollup STATUS: REAL cost rollup raw + pkg + labor + overhead + freight vs prior drift BACKEND · cost_surface i CAPACITY CHECK — Confirm labor hours available and components in inventory. Block or queue if either fails. ACTION labor: timebill_capacity vs bom.labor_min × qty components: inventory_balance.quantityavailable per line TABLES read: inventory_balance · employees (capacity) STATUS components_check: REAL labor_capacity: STUB (manual judgement) capacity check labor + components block if short CAPACITY · STUB labor i HITL AUTHORIZATION — If rollup cost > threshold (default $5K) or drift_pct_vs_prior > 8%, proposed_action staged. Mike approves via /proposed-actions.html. THRESHOLD cost_abs: $5,000 drift_pct: 8% HITL action_type: 'assembly_build_authorize' surface: /proposed-actions.html TABLES write: proposed_actions STATUS: REAL · risk 3 HITL authorize cost > $5K drift > 8% Mike approves SECURITY · risk 3 i COMPONENT CONSUMPTION — Debit inventory_balance per BOM line for the build qty. NS posts assemblyunbuild reverse only if rollback; forward path posts inventoryadjustment or workorderissue child. ACTION decrement: inventory_balance per BOM line ns_record: linked workorderissue OR direct inventoryadjustment TABLES write: inventory_balance · transactions STATUS: REAL consumption debit inventory per BOM line DATABASE · -qty i BUILD OPERATION — Physical production of the assembly happens on the floor; system-side this is the NS 'build' transaction record that links consumption to creation. ACTION ns_record: assemblybuild (Build txn) link: parent_wo_id if WO-driven TABLES write: transactions (Build) STATUS: REAL build operation assemblybuild physical produce BACKEND · Build txn i ASSEMBLY CREATED — Credit inventory_balance for the assembly item at the production location. Assembly available for sales allocation. ACTION increment: inventory_balance (assembly_id, +qty) TABLES write: inventory_balance · assemblies STATUS: REAL assembly created credit FG qty available DATABASE · +qty i SPEC SHEET REFRESH — If claims, allergens, or pack format changed in the BOM since last spec render, regenerate via spec-sheet-pipeline workflow. Otherwise skip. TRIGGER diff: claims OR allergens OR pack_format changed WORKFLOW invoke: spec-sheet-pipeline endpoint: POST /api/specs/ingest TABLES write: spec_items (new spec_version) r2: specs/<item_code>/<version>.pdf STATUS: REAL · invoked when needed spec sheet refresh if claims changed spec-sheet-pipeline new spec_version CLOUD · linked workflow i COST RECALC — assembly_cost_rollup re-runs with the final actuals. drift_pct_vs_prior surfaced on the item entity page and admin-dashboard cost-surface tile. ACTION compute: assembly_cost_rollup with actuals surface: drift_pct_vs_prior TABLES write: assembly_cost_rollup (status=active) SURFACES /item/<code> · admin-dashboard cost tile STATUS: REAL cost recalc final actuals drift_pct surfaced cost tile updated BACKEND · cost-surface i drift feeds next build's rollup baseline LEGEND Frontend Database Backend Cloud / linked HITL Capacity

1 · Trigger FIRES WHEN…

kind
manual_or_event
event pattern
build.requested
description
Manual chat-tool request OR fulfillment shortfall event

2 · Inputs required

namerequiredtype / hint
assembly_idrequiredinteger
qtyrequiredinteger
location_idrequiredinteger
reasonoptionalstring

3 · Context loaded D1 queries run before fan-out

name
assembly
tables
assemblies
returns
row
SELECT
  id, itemid, displayname, quantityavailable
  FROM assemblies
  WHERE id = ?
name
current_bom
tables
assembly_bom
returns
rows
SELECT
  item_code, qty, uom, estimated_cost
  FROM assembly_bom
  WHERE assembly_id = ?
name
on_hand
tables
inventory_balance · assembly_bom
returns
rows
SELECT
  item_code, quantityavailable
  FROM inventory_balance
  WHERE location_id = ?
  AND item_code IN (SELECT item_code
  FROM assembly_bom
  WHERE assembly_id = ?)
name
cost_rollup
tables
assembly_cost_rollup
returns
row
SELECT
  computed_at, total_cost
  FROM assembly_cost_rollup
  WHERE assembly_id = ?
  ORDER BY computed_at DESC
  LIMIT 1

4 · Preconditions checked before any fan-out

checkruleseverity
assembly_existsassembly_id IN (SELECT id FROM assemblies)block
qty_positiveqty > 0block
location_validlocation_id IN (SELECT id FROM locations WHERE active=1)block
components_on_handevery BOM line.on_hand >= qty * bom.qtywarn

5 · HITL gate

Risk level 2 < 3 — no HITL gate. Fan-out runs immediately after preconditions pass.

6 · Fan-out targets 10 total · 3 real · 7 stub

#1snapshot_cost d1_write STUB

table
assembly_cost_rollup
operation
insert
stub — not yet implemented in src/lib/workflow_runner.ts (kind d1_write hits the placeholder branch). Documented intent only.
INSERT INTO assembly_cost_rollup (assembly_id, total_cost, computed_at, source)
  VALUES (?,?,datetime('now'),'build_request')

#2draft_proposal stage_proposed_action REAL

action_type
assembly_build
entity_type
assembly

#3hitl_approve stage_proposed_action REAL

action_type
assembly_build_approval
entity_type
workflow_run

#4ns_push_build ns_push STUB

NS record_type
assemblybuild
queue
NS_PUSH_QUEUE
on_failure
retry_3_then_alert
stub — not yet implemented in src/lib/workflow_runner.ts (kind ns_push hits the placeholder branch). Documented intent only.

#5d1_inventory_decrement d1_write STUB

table
inventory_balance
operation
update
stub — not yet implemented in src/lib/workflow_runner.ts (kind d1_write hits the placeholder branch). Documented intent only.
UPDATE inventory_balance
  SET quantityavailable = quantityavailable - ?
  WHERE item_code = ?
  AND location_id = ?

#6d1_inventory_increment d1_write STUB

table
inventory_balance
operation
update
stub — not yet implemented in src/lib/workflow_runner.ts (kind d1_write hits the placeholder branch). Documented intent only.
UPDATE inventory_balance
  SET quantityavailable = quantityavailable + ?
  WHERE item_code = (SELECT itemid
  FROM assemblies
  WHERE id=?)
  AND location_id = ?

#7kv_invalidate_assembly kv_invalidate REAL

keys
assembly:?assembly_id
inventory:item:?assembly_id

#8variance_flag flag STUB

table
proposed_actions
field
action_type
value
build_cost_variance
condition (if)
abs((actual_cost - estimated_cost)/estimated_cost) > 0.05
stub — not yet implemented in src/lib/workflow_runner.ts (kind flag hits the placeholder branch). Documented intent only.

#9refresh_quotes http_call STUB

method
POST
path
/api/quotes/refresh-by-assembly
condition (if)
open_quotes_touching_assembly > 0
stub — not yet implemented in src/lib/workflow_runner.ts (kind http_call hits the placeholder branch). Documented intent only.

#10reflexion_write d1_write STUB

table
reflexion_log
operation
insert
stub — not yet implemented in src/lib/workflow_runner.ts (kind d1_write hits the placeholder branch). Documented intent only.
INSERT INTO reflexion_log (workflow_run_id, entity_type, entity_id, outcome, tags)
  VALUES (?,'assembly',?,?,'assembly_build')

7 · Post actions declared + runner-automatic

idactionsource
runner_log_runINSERT into workflow_run_log (run_id, workflow_type, status, started_at, completed_at, summary_json)runner automatic
runner_reflexionINSERT into reflexion_log (tags=assembly_build_request, run_id, narrative)runner automatic (reflexion_enabled=1)
log_runINSERT workflow_run_logdeclared in contract
reflexionINSERT reflexion_log with tags=assembly_builddeclared in contract
event_completedFIRE event workflow.completed (workflow_type=assembly_build_request)declared in contract

8 · Verify checks written to workflow_verify_results

name
build_recorded_in_d1
when_to_run
15 min after run
expected
row
SELECT
  id
  FROM transactions
  WHERE type='Build'
  AND assembly_id=?
  AND created_at > datetime('now','-15 minutes')
name
inventory_credited
when_to_run
15 min after run
expected
increased by ?qty
SELECT
  quantityavailable
  FROM inventory_balance
  WHERE item_code=(SELECT itemid
  FROM assemblies
  WHERE id=?)
  AND location_id=?
name
ns_push_applied
when_to_run
30 min after run
expected
applied
SELECT
  status
  FROM ns_pending_pushes
  WHERE record_type='assemblybuild'
  AND payload_json LIKE '%assembly_id?%'

9 · Retry policy

max_attempts
3
backoff
exponential
base_ms
2000
max_ms
30000
alert_on_final_failure
true

10 · What changes when this workflow runs aggregated side effects

systemtable / resourceactionstatussource
D1proposed_actionsINSERT (action_type=assembly_build)REALfan-out #2 (draft_proposal)
D1proposed_actionsINSERT (action_type=assembly_build_approval)REALfan-out #3 (hitl_approve)
KV (CACHE)assembly:?assembly_id, inventory:item:?assembly_idinvalidateREALfan-out #7 (kv_invalidate_assembly)
D1workflow_run_logINSERT (run summary)REALrunner automatic
D1reflexion_logINSERT (tags=assembly_build_request)REALrunner automatic
Eventworkflow.completed (or workflow.failed)fireREALrunner automatic
D1workflow_verify_resultsINSERT pending × 3REALrunner verify staging
D1assembly_cost_rollupinsertSTUBfan-out #1 (snapshot_cost)
NetSuite (via NS_PUSH_QUEUE)assemblybuildpushSTUBfan-out #4 (ns_push_build)
D1inventory_balanceupdateSTUBfan-out #5 (d1_inventory_decrement)
D1inventory_balanceupdateSTUBfan-out #6 (d1_inventory_increment)
D1proposed_actionsset action_type=build_cost_varianceSTUBfan-out #8 (variance_flag)
Worker HTTPPOST /api/quotes/refresh-by-assemblyinvokeSTUBfan-out #9 (refresh_quotes)
D1reflexion_loginsertSTUBfan-out #10 (reflexion_write)