{"id":10004,"date":"2026-09-24T13:50:00","date_gmt":"2026-09-24T20:50:00","guid":{"rendered":"https:\/\/fargotechs.com\/?page_id=10004"},"modified":"2026-09-24T13:50:00","modified_gmt":"2026-09-24T20:50:00","slug":"operational-dashboard","status":"publish","type":"page","link":"https:\/\/fargotechs.com\/?page_id=10004","title":{"rendered":"Operational Dashboard"},"content":{"rendered":"\n<style>\n:root{--navy:#1f4e79;--blue:#2e75b6;--bg:#f4f6f8;--card:#fff;--ok:#2e7d32;--warn:#b26a00;--bad:#c62828;--line:#d9dee3;}\n*{box-sizing:border-box;margin:0;padding:0;font-family:-apple-system,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;}\nbody{background:var(--bg);color:#222;font-size:14px;}\nheader{background:var(--navy);color:#fff;padding:12px 22px;display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:8px;}\nheader h1{font-size:16px;font-weight:600;}\n.badge{background:#fff2cc;color:#7a5c00;padding:3px 10px;border-radius:12px;font-size:10.5px;font-weight:700;line-height:1.3;}\nnav{background:#fff;border-bottom:1px solid var(--line);padding:0 8px;display:flex;flex-wrap:wrap;}\nnav button{background:none;border:none;padding:11px 12px;cursor:pointer;font-size:12.5px;color:#555;border-bottom:3px solid transparent;}\nnav button.active{color:var(--navy);border-bottom-color:var(--blue);font-weight:600;}\nmain{padding:16px 22px;max-width:1200px;margin:0 auto;}\n.card{background:var(--card);border:1px solid var(--line);border-radius:8px;padding:15px;margin-bottom:14px;}\n.card h2{font-size:14.5px;color:var(--navy);margin-bottom:9px;}\n.card h3{font-size:12.5px;margin:9px 0 5px;color:#444;}\n.kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(135px,1fr));gap:10px;margin-bottom:14px;}\n.kpi{background:var(--card);border:1px solid var(--line);border-radius:8px;padding:12px;text-align:center;}\n.kpi .v{font-size:24px;font-weight:700;color:var(--navy);}\n.kpi .l{font-size:10px;color:#777;text-transform:uppercase;letter-spacing:.4px;margin-top:3px;}\ntable{width:100%;border-collapse:collapse;font-size:12px;}\nth{background:#eef2f6;text-align:left;padding:6px 8px;border:1px solid var(--line);font-weight:600;}\ntd{padding:5px 8px;border:1px solid var(--line);vertical-align:top;}\n.pill{display:inline-block;padding:2px 8px;border-radius:10px;font-size:10.5px;font-weight:600;}\n.pill.g{background:#e2efda;color:var(--ok);}.pill.y{background:#fff2cc;color:var(--warn);}.pill.r{background:#fce4ec;color:var(--bad);}.pill.b{background:#ddebf7;color:var(--navy);}\nbutton.act{background:var(--blue);color:#fff;border:none;padding:7px 13px;border-radius:6px;cursor:pointer;font-size:12px;margin:2px 4px 2px 0;}\nbutton.act:hover{background:var(--navy);}\nbutton.ghost{background:#fff;color:var(--navy);border:1px solid var(--blue);}\nbutton.warn{background:var(--bad);}\nselect,input{padding:6px;border:1px solid var(--line);border-radius:5px;font-size:12px;margin-right:6px;}\n.log{font-family:Menlo,Consolas,monospace;font-size:11px;background:#0f172a;color:#cde3ff;padding:10px;border-radius:6px;max-height:240px;overflow:auto;white-space:pre-wrap;}\n.testrow td:first-child{width:38px;text-align:center;font-weight:700;}\n.p-ok{color:var(--ok);}.p-fail{color:var(--bad);}\n.note{font-size:11px;color:#666;font-style:italic;margin-top:6px;}\n.note.lim{background:#fff8e6;border:1px solid #ecd9a0;color:#6b5416;font-style:normal;padding:10px 13px;border-radius:6px;}\n.grid2{display:grid;grid-template-columns:1fr 1fr;gap:14px;}\n@media(max-width:900px){.grid2{grid-template-columns:1fr;}}\n.kbd{font-family:monospace;background:#eef2f6;padding:1px 5px;border-radius:4px;}\n<\/style><style>body.elementor-template-canvas{margin:0} .e-con,.elementor-widget-container{padding:0} @media(max-width:600px){h1.hero-title{font-size:32px}.section{padding:36px 18px}.nav{display:flex;flex-wrap:wrap;gap:12px}.nav a{margin-left:0}.credits{overflow:auto}}<\/style>\n\n<div style=\"padding:12px 20px;background:#fff\"><a href=\"\/\">\u2190 Fargo Techs home<\/a> \u00b7 <a href=\"\/?pagename=visual-journey\">Visual journey<\/a><\/div><header>\n  <h1>Returnable Container Traceability \u2014 Closed-Loop Demo<\/h1>\n  <span class=\"badge\">SYNTHETIC DATA \u00b7 SIMULATED HARDWARE \u00b7 INTERACTIVE DEMO<br>NOT CONNECTED TO ANY PRODUCTION OR CUSTOMER SYSTEM<\/span>\n<\/header>\n<nav id=\"nav\"><\/nav>\n<main id=\"main\"><\/main>\n\n<script>\n\"use strict\";\n\/* ================= SYNTHETIC DATA & CORE MODEL =================\n   All bins, EPCs, sites, scans are generated locally for demonstration.\n   \"Simulated hardware\" = RFID handheld \/ portal reads are mock function\n   calls (ingest) with no real readers attached. No production WMS, cloud,\n   auth, or multi-user concurrency is implemented. See \"Labels & limitations\". *\/\nconst BOX = {model:\"Illustrative collapsible container (810 mm scenario)\", h:810, lid:15, folded:250, source:\"Synthetic planning inputs only \u2014 not a supplier specification or loading approval\"};\nconst TRUCK = {clearHeight:2000, doorHeight:1900, note:\"Illustrative truck dimensions \u2014 actual vehicle measurement required\"};\nconst SITES = {WH:\"Warehouse WH1\", SA:\"Store A\", SB:\"Store B\", TRUCK:\"Truck (in transit)\", WB:\"Wash\/Inspect Bay\"};\nconst GROUND = [SITES.WH, SITES.SA, SITES.SB, SITES.WB]; \/\/ truck is transit, not a custody site\n\nlet assets, tags, trips, events, exceptions, idemSeen, seq, consistencyLog;\nfunction freshState(){\n  seq=100; idemSeen=new Set(); consistencyLog=[];\n  assets={}; tags={}; trips=[]; events=[]; exceptions=[];\n  \/\/ 24 bins commissioned at the warehouse, available for redeployment\n  for(let i=1;i<=24;i++){\n    const id=\"AST-\"+String(i).padStart(3,\"0\");\n    const epc=\"E280.6894.0000.000\"+String(100+i);\n    assets[id]={id, model:BOX.model, status:\"active\", confirmedSite:SITES.WH, lastSite:SITES.WH, lastRead:null, contents:null, createdAt:ts0(i)};\n    tags[epc]={epc, assetId:id, position:\"body\", status:\"active\"};\n    assets[id].epcs=[epc];\n    logEvent({type:\"COMMISSION\", assetId:id, epc, site:SITES.WH, src:\"handheld\", op:\"OP-01\", idemKey:\"seed-\"+i, at:ts0(i)});\n  }\n}\nfunction ts0(i){const d=new Date(\"2026-09-23T08:00:00\");d.setMinutes(d.getMinutes()+i*3);return d.toISOString();}\nfunction now(){return new Date().toISOString();}\nfunction logEvent(e){e.ingestedAt=now();e.eventId=\"EV-\"+(++seq);events.push(e);return e;}\n\n\/* ingestion with idempotency + burst dedup + conflict detection (ground sites only) *\/\nfunction ingest(type, assetId, epc, site, src, op, idemKey, offline){\n  if(!assets[assetId]) return {status:\"UNKNOWN_ASSET\", key:idemKey}; \/\/ reads never create phantom assets\n  if(idemSeen.has(idemKey)) return {status:\"DUPLICATE_IDEMPOTENCY\", key:idemKey};\n  \/\/ burst dedup only applies to scan-type reads; operator actions (TAG_REPLACED, FILL, etc.) are never deduped\n  const SCAN=[\"DISPATCH\",\"RECEIPT\",\"MOVE\",\"RETURN\"];\n  const last=[...events].reverse().find(ev=>ev.assetId===assetId&&ev.site===site&&SCAN.includes(ev.type));\n  if(SCAN.includes(type)&&last && (Date.parse(now())-Date.parse(last.ingestedAt))<60000) return {status:\"DEDUPED_BURST\", key:idemKey};\n  idemSeen.add(idemKey);\n  const a=assets[assetId];\n  const ev=logEvent({type, assetId, epc, site, src, op, idemKey, offline:!!offline, observedAt:now()});\n  \/\/ conflict: a read at a DIFFERENT GROUND site within 2 min of the last movement read.\n  \/\/ Truck (in transit) is transient and does NOT conflict with its destination.\n  const recent=[...events].reverse().find(x=>x.assetId===assetId&&x.site!==site&&GROUND.includes(x.site)&&[\"DISPATCH\",\"RECEIPT\",\"MOVE\",\"RETURN\"].includes(x.type));\n  if(recent && Math.abs(Date.parse(ev.ingestedAt)-Date.parse(recent.ingestedAt))<120000){\n    a.lastSite=site; a.lastRead=now();\n    exceptions.push({id:\"EX-\"+(++seq), assetId, kind:\"CONFLICTING_OBSERVATION\", detail:`Read at ${site} within 2 min of ${recent.site} \u2014 both events retained; custody unconfirmed until operator resolves`, resolved:false});\n    return {status:\"CONFLICT\", event:ev};\n  }\n  a.lastSite=site; a.lastRead=now();\n  return {status:\"OK\", event:ev};\n}\nfunction confirmLocation(assetId, site){\n  const a=assets[assetId]; a.confirmedSite=site;\n  logEvent({type:\"LOCATION_CONFIRMED\", assetId, site, src:\"manual\", op:\"SUP-01\", idemKey:\"conf-\"+(++seq)});\n}\n\n\/* trips (multi-stop, multi-store) *\/\nfunction createTrip(kind, legs){ \/\/ legs=[{site,dir:'deliver'|'pickup',items:[]}]\n  const t={id:\"TR-\"+(++seq), kind, legs, status:\"DRAFT\", manifest:null, received:null, createdAt:now()};\n  trips.push(t); return t;\n}\nfunction loadTrip(tripId){\n  const t=trips.find(x=>x.id===tripId); let loaded=[];\n  for(const leg of t.legs){\n    for(const id of leg.items){\n      const r=ingest(\"DISPATCH\", id, assets[id].epcs[0], SITES.TRUCK, \"handheld\", \"OP-02\", \"ld-\"+id+\"-\"+tripId);\n      if(r.status===\"OK\"||r.status===\"CONFLICT\") loaded.push(id);\n    }\n  }\n  t.status=\"IN_TRANSIT\";\n  t.manifest={tripId, kind:t.kind, stops:t.legs.map(l=>({site:l.site,dir:l.dir,count:l.items.length})), items:t.legs.flatMap(l=>l.items), generatedAt:now()};\n  return loaded;\n}\nfunction arriveStop(tripId, legIdx){\n  const t=trips.find(x=>x.id===tripId); const leg=t.legs[legIdx]; let done=[];\n  for(const id of leg.items){\n    const r=ingest(\"RECEIPT\", id, assets[id].epcs[0], leg.site, leg.dir===\"deliver\"?\"handheld\":\"portal\", \"OP-03\", \"ar-\"+id+\"-\"+tripId);\n    if(r.status===\"OK\"||r.status===\"CONFLICT\"){ assets[id].confirmedSite=leg.site; done.push(id); }\n  }\n  return done;\n}\nfunction receiveAtWH(tripId, scannedIds){\n  const t=trips.find(x=>x.id===tripId);\n  const rec={scanned:scannedIds.slice(), missing:[], extra:[], reconciled:false, at:now()};\n  for(const id of t.legs.flatMap(l=>l.items)) if(!scannedIds.includes(id)) rec.missing.push(id);\n  for(const id of scannedIds) if(!t.legs.flatMap(l=>l.items).includes(id)) rec.extra.push(id);\n  for(const id of scannedIds.filter(x=>t.legs.flatMap(l=>l.items).includes(x))){ ingest(\"RECEIPT\", id, assets[id].epcs[0], SITES.WH, \"portal\", \"OP-03\", \"rc-\"+id+\"-\"+tripId); assets[id].confirmedSite=SITES.WH; }\n  t.received=rec; t.status=rec.missing.length||rec.extra.length?\"EXCEPTION\":\"RECONCILED\";\n  if(t.status===\"EXCEPTION\") exceptions.push({id:\"EX-\"+(++seq), assetId:rec.missing[0]||rec.extra[0], kind:\"RECEIVING_MISMATCH\", detail:`${t.id}: missing ${rec.missing.length}, extra ${rec.extra.length} \u2014 reconcile before closing`, resolved:false});\n  return rec;\n}\nfunction fillStore(site, ids, contents){\n  for(const id of ids){ assets[id].contents=contents; logEvent({type:\"FILL\", assetId:id, site, src:\"manual\", op:\"OP-05\", idemKey:\"fill-\"+id, contents}); }\n  return ids.length;\n}\nfunction emptyReturn(ids, site){\n  for(const id of ids){ assets[id].contents=null; ingest(\"EMPTY_RETURN\", id, assets[id].epcs[0], site, \"handheld\", \"OP-04\", \"er-\"+id); assets[id].confirmedSite=site; }\n  return ids.length;\n}\nfunction inspect(ids){\n  for(const id of ids){ assets[id].status=\"active\"; logEvent({type:\"INSPECT\", assetId:id, site:SITES.WH, src:\"manual\", op:\"OP-06\", idemKey:\"ins-\"+id, result:\"passed\"}); }\n  return ids.length;\n}\nfunction replaceTag(assetId, reason){\n  const a=assets[assetId]; const old=a.epcs[0]; tags[old].status=\"retired\";\n  const nepc=\"E280.6894.0000.000\"+String(900+(++seq)%99);\n  tags[nepc]={epc:nepc, assetId, position:\"body\", status:\"active\"}; a.epcs.unshift(nepc);\n  logEvent({type:\"TAG_REPLACED\", assetId, epc:nepc, site:a.confirmedSite, src:\"manual\", op:\"SUP-01\", idemKey:\"tag-\"+(++seq), detail:`old EPC ${old} retired; asset ID stable`});\n  return {old, nepc};\n}\n\n\/* truck height feasibility (nominal arithmetic only \u2014 NOT loading verification) *\/\nfunction stackHeight(n){\n  const bodies810=2*BOX.h, bodies1000=2*1000;\n  return {\n    perStack810:bodies810, perStack1000:bodies1000,\n    verdict810: bodies810<=TRUCK.clearHeight ? `FEASIBLE (nominal bodies ${bodies810} mm; +lid ~${BOX.lid} mm) \u2014 physical verification required` : \"EXCEEDS\",\n    verdict1000: bodies1000>=TRUCK.clearHeight ? `BODIES = ${bodies1000} mm = FULL CLEARANCE; +lid EXCEEDS ${TRUCK.clearHeight} mm \u2014 DO NOT CLAIM` : \"FEASIBLE\"\n  };\n}\n\n\/* inventory consistency guard: one custody state per asset, totals reconcile, no phantom assets *\/\nfunction inventoryConsistency(){\n  const issues=[];\n  const ids=Object.keys(assets);\n  if(new Set(ids).size!==ids.length) issues.push(\"duplicate asset keys\");\n  for(const a of Object.values(assets)){\n    if(!a.confirmedSite) issues.push(a.id+\" has no confirmed custody site\");\n    if(!GROUND.includes(a.confirmedSite)) issues.push(a.id+\" confirmedSite is transit\/garbage\");\n  }\n  const total=ids.length;\n  const bySite={}; GROUND.forEach(s=>bySite[s]=0);\n  Object.values(assets).forEach(a=>{ if(bySite[a.confirmedSite]!==undefined) bySite[a.confirmedSite]++; });\n  const sum=Object.values(bySite).reduce((x,y)=>x+y,0);\n  if(sum!==total) issues.push(`totals unreconciled: custody sum ${sum} != assets ${total}`);\n  return {ok:issues.length===0, issues, bySite, total};\n}\n\n\/* persistence (best-effort; no-op when localStorage unavailable, e.g. headless) *\/\nconst STORE_KEY=\"fargoRCT_v2\";\nfunction save(){ try{ localStorage.setItem(STORE_KEY, JSON.stringify({v:2,assets,tags,trips,events,exceptions,idemSeen:[...idemSeen],seq})); }catch(e){} }\nfunction load(){ try{ const s=localStorage.getItem(STORE_KEY); if(!s) return false; const d=JSON.parse(s); if(d.v!==2) return false;\n  assets=d.assets; tags=d.tags; trips=d.trips; events=d.events; exceptions=d.exceptions; idemSeen=new Set(d.idemSeen); seq=d.seq; return true; }catch(e){ return false; } }\nfunction resetDemo(){ try{ localStorage.removeItem(STORE_KEY); }catch(e){} freshState(); e2eSteps=[]; tab=\"Dashboard\"; renderNav(); render(); save(); }\nlet resetArmed=false;\nfunction armReset(){ const b=document.getElementById(\"resetBtn\"); if(!resetArmed){ resetArmed=true; b.textContent=\"Click again to CONFIRM reset\"; setTimeout(()=>{resetArmed=false; if(b.isConnected)b.textContent=\"Reset demo\";},4000); } else { resetArmed=false; resetDemo(); } }\n\n\/* ================= UI ================= *\/\nconst TABS=[\"Dashboard\",\"Guided Walkthrough\",\"Trips & Truck\",\"Receiving\",\"Fill & Return\",\"Exceptions\",\"Asset Registry\",\"Event Log\",\"Scenario Tests\",\"Logic Tests\"];\nlet tab=\"Dashboard\";\nconst $=s=>document.querySelector(s);\nfunction pill(s){const c=s.includes(\"OK\")||s.includes(\"RECONCILED\")||s.includes(\"FEASIBLE\")?\"g\":s.includes(\"EXCEPT\")||s.includes(\"EXCEED\")||s.includes(\"MISSING\")?\"r\":s.includes(\"TRANSIT\")||s.includes(\"DRAFT\")||s.includes(\"PENDING\")?\"y\":\"b\";return `<span class=\"pill ${c}\">${s}<\/span>`;}\nfunction renderNav(){ $(\"#nav\").innerHTML=TABS.map(t=>`<button class=\"${t===tab?'active':''}\" onclick=\"setTab('${t}')\">${t}<\/button>`).join(\"\"); }\nfunction setTab(t){tab=t;renderNav();render();}\nfunction kpi(v,l){return `<div class=\"kpi\"><div class=\"v\">${v}<\/div><div class=\"l\">${l}<\/div><\/div>`;}\nfunction assetRow(id){const a=assets[id];return `<tr><td><b>${id}<\/b><\/td><td>${a.epcs[0]}<\/td><td>${a.lastSite}<\/td><td>${pill(a.confirmedSite===a.lastSite?\"CONFIRMED\":\"UNCONFIRMED\")}<\/td><td>${a.contents?`<span class=\"pill b\">DECLARED<\/span> ${a.contents}`:\"<i>none recorded<\/i>\"}<\/td><td>${a.status}<\/td><\/tr>`}\nfunction render(){\n  const m=$(\"#main\");\n  if(tab===\"Dashboard\"){\n    const cons=inventoryConsistency();\n    const byObs={}; Object.values(assets).forEach(a=>byObs[a.lastSite]=(byObs[a.lastSite]||0)+1);\n    const open=exceptions.filter(e=>!e.resolved).length;\n    const transit=trips.filter(t=>t.status===\"IN_TRANSIT\").length;\n    const avail=Object.values(assets).filter(a=>a.confirmedSite===SITES.WH&&!a.contents).length;\n    m.innerHTML=`\n    <div class=\"kpis\">${kpi(Object.keys(assets).length,\"Active assets\")}${kpi(avail,\"Available @ WH\")}${kpi(byObs[SITES.SA]||0,\"Last observed @ Store A\")}${kpi(byObs[SITES.SB]||0,\"Last observed @ Store B\")}${kpi(byObs[SITES.TRUCK]||0,\"In transit\")}${kpi(transit,\"Open trips\")}${kpi(open,\"Unresolved exceptions\")}<\/div>\n    <div class=\"card\"><h2>Inventory consistency (custody = confirmed site)<\/h2>\n    <table><tr><th>Site (confirmed custody)<\/th><th>Assets<\/th><\/tr>\n    ${GROUND.map(s=>`<tr><td>${s}<\/td><td>${cons.bySite[s]||0}<\/td><\/tr>`).join(\"\")}\n    <tr><td><b>Total reconciled<\/b><\/td><td><b>${cons.total}<\/b> ${pill(cons.ok?\"RECONCILED\":\"MISMATCH\")}<\/td><\/tr><\/table>\n    <p class=\"note\">\"Last observed\" = most recent read. \"Confirmed custody\" = operator-verified. Passive UHF gives event-based location, not continuous tracking. One custody state per asset by design.<\/p><\/div>\n    <div class=\"card\"><h2>Reset &amp; quick start<\/h2>\n    <button class=\"act warn\" id=\"resetBtn\" onclick=\"armReset()\">Reset demo<\/button>\n    <button class=\"act\" onclick=\"setTab('Guided Walkthrough')\">Open guided 5-minute walkthrough \u2192<\/button>\n    <p class=\"note\">State <b>persists across page refresh<\/b> (saved to this browser's localStorage). \"Reset demo\" clears it and reseeds 24 bins at the warehouse. This is local only \u2014 no server.<\/p><\/div>\n    <div class=\"card\"><h2>Labels &amp; limitations<\/h2>\n    <div class=\"note lim\"><b>SIMULATED HARDWARE:<\/b> every RFID handheld\/portal read is a mock function call \u2014 no real readers, tags, antennas, or gateways are attached.<br>\n    <b>SYNTHETIC DATA:<\/b> all bins (AST-###), EPCs, sites, and scan events are generated for the demo. No customer, no real inventory.<br>\n    <b>NOT IMPLEMENTED:<\/b> production WMS\/ERP integration, cloud sync, user auth, multi-user concurrency, real RFID hardware, GPS tracking, and automated report delivery. The demo shows the closed-loop <i>logic<\/i> only.<\/div><\/div>`;\n  }\n  else if(tab===\"Guided Walkthrough\"){\n    m.innerHTML=`<div class=\"card\"><h2>Guided 5-minute walkthrough \u2014 full closed loop (2 stores, multi-stop trip)<\/h2>\n    <p>One click runs the entire cycle end-to-end on the real UI functions: warehouse empties \u2192 deliver to Store A &amp; Store B (multi-stop) \u2192 fill at both stores \u2192 pickup (multi-stop) \u2192 warehouse receipt &amp; reconcile \u2192 empty\/inspect \u2192 available for redeployment. Each step is logged below.<\/p>\n    <button class=\"act\" onclick=\"runGuidedE2E()\">\u25b6 Run full closed-loop demo<\/button>\n    <button class=\"act ghost\" onclick=\"resetDemo();runGuidedE2E();\">\u21ba Reset then run<\/button>\n    <div id=\"e2e\" class=\"log\">${e2eSteps.length?e2eSteps.join(\"\\n\"):\"\"}<\/div>\n    <p class=\"note\">After running, open <b>Dashboard<\/b> to see all 24 bins back at the warehouse available for redeployment; open <b>Event Log<\/b> for the full append-only trail.<\/p><\/div>`;\n  }\n  else if(tab===\"Trips & Truck\"){\n    const drafts=trips.filter(t=>t.status===\"DRAFT\");\n    const transit=trips.filter(t=>t.status===\"IN_TRANSIT\");\n    const sh=stackHeight(2);\n    m.innerHTML=`<div class=\"card\"><h2>Create trip (delivery of empties, multi-stop)<\/h2>\n    <select id=\"dsa\"><option value=\"6\">Store A: 6 empties<\/option><option value=\"4\">Store A: 4 empties<\/option><\/select>\n    <select id=\"dsb\"><option value=\"6\">Store B: 6 empties<\/option><option value=\"4\">Store B: 4 empties<\/option><\/select>\n    <button class=\"act\" onclick=\"mkDelivery()\">Create delivery trip (WH\u2192A\u2192B)<\/button>\n    <div id=\"mkd\"><\/div><\/div>\n    <div class=\"card\"><h2>Load truck &amp; arrive at stops<\/h2>\n    ${drafts.length?`<b>Draft trips:<\/b> `+drafts.map(t=>`<button class=\"act\" onclick=\"loadTripUI('${t.id}')\">Load ${t.id}<\/button>`).join(\"\"):\"<i>No draft trips.<\/i>\"}\n    ${transit.length?`<br><b>In transit:<\/b> `+transit.map(t=>`<button class=\"act ghost\" onclick=\"arriveNext('${t.id}')\">Arrive next stop (${t.legs[t._at||0]?t.legs[t._at||0].site:'done'})<\/button>`).join(\"\"):\"<i>No trips in transit.<\/i>\"}\n    <div id=\"tripres\"><\/div><\/div>\n    <div class=\"card\"><h2>Truck height feasibility (nominal only)<\/h2>\n    <table><tr><th>Config<\/th><th>Nominal stacked (bodies)<\/th><th>vs ~${TRUCK.clearHeight} mm clear<\/th><\/tr>\n    <tr><td>2 \u00d7 ${BOX.h} mm + lid<\/td><td>${sh.perStack810} mm<\/td><td>${pill(sh.verdict810)}<\/td><\/tr>\n    <tr><td>2 \u00d7 1000 mm + lid (deprioritized)<\/td><td>${sh.perStack1000} mm<\/td><td>${pill(sh.verdict1000)}<\/td><\/tr><\/table>\n    <p class=\"note\">Nominal arithmetic is NOT verification. Measure actual stacked height incl. lid, door opening (${TRUCK.doorHeight} mm), forklift clearance, and legal stacking limits before claiming any arrangement works.<\/p><\/div>`;\n  }\n  else if(tab===\"Receiving\"){\n    const transit=trips.filter(t=>t.status===\"IN_TRANSIT\" && t.kind===\"pickup\");\n    m.innerHTML=`<div class=\"card\"><h2>Receive at Warehouse WH1 (simulated portal sweep)<\/h2>\n    ${transit.length?`<select id=\"rt\">${transit.map(t=>`<option>${t.id}<\/option>`).join(\"\")}<\/select>\n    <button class=\"act\" onclick=\"receiveUI(true)\">Simulate FULL scan<\/button>\n    <button class=\"act ghost\" onclick=\"receiveUI(false)\">Simulate PARTIAL scan (miss 1)<\/button>\n    <div id=\"rcres\"><\/div>`:\"<i>No pickup trips in transit \u2014 create one via Fill &amp; Return, then a pickup trip.<\/i>\"}<\/div>`;\n  }\n  else if(tab===\"Fill & Return\"){\n    m.innerHTML=`<div class=\"card\"><h2>Fill stores &amp; create pickup trip<\/h2>\n    <p>After delivery, bins sit empty at the stores. <b>Fill<\/b> declares what each store loaded (asset \u2260 contents), then create a <b>pickup trip<\/b> collecting them back to WH.<\/p>\n    <button class=\"act\" onclick=\"fillStores()\">Declare fill @ Store A &amp; Store B (demo contents)<\/button>\n    <button class=\"act ghost\" onclick=\"mkPickup()\">Create pickup trip (A\u2192B\u2192WH)<\/button>\n    <div id=\"fillres\"><\/div><\/div>\n    <div class=\"card\"><h2>Empty \/ inspect at Warehouse (redeployment)<\/h2>\n    <button class=\"act\" onclick=\"emptyInspect()\">Empty + inspect all received full bins; return to available<\/button>\n    <div id=\"erres\"><\/div>\n    <p class=\"note\">On empty return, the DECLARED contents association is cleared; asset ID, tag, and history persist. Reading a box tag never establishes contents.<\/p><\/div>`;\n  }\n  else if(tab===\"Exceptions\"){\n    m.innerHTML=`<div class=\"card\"><h2>Exception queue<\/h2>\n    <table><tr><th>ID<\/th><th>Kind<\/th><th>Asset<\/th><th>Detail<\/th><th>Action<\/th><\/tr>\n    ${exceptions.map(e=>`<tr><td><b>${e.id}<\/b><\/td><td>${e.kind}<\/td><td>${e.assetId}<\/td><td>${e.detail}<\/td><td>${e.resolved?'<span class=\"pill g\">RESOLVED<\/span>':`<button class=\"act\" onclick=\"resolveEx('${e.id}')\">Resolve \u2192 confirm last read<\/button>`}<\/td><\/tr>`).join(\"\")||\"<tr><td colspan=5><i>No exceptions. Trigger one via Receiving (partial) or a wrong-location scan in Scenario Tests.<\/i><\/td><\/tr>\"}<\/table><\/div>`;\n  }\n  else if(tab===\"Asset Registry\"){\n    m.innerHTML=`<div class=\"card\"><h2>Asset registry \u2014 stable asset ID vs tag vs contents<\/h2>\n    <table><tr><th>Asset<\/th><th>Current EPC<\/th><th>Last observed<\/th><th>Custody<\/th><th>Contents (DECLARED)<\/th><th>Status<\/th><\/tr>\n    ${Object.keys(assets).slice(0,14).map(assetRow).join(\"\")}<\/table>\n    <p class=\"note\">Showing first 14 of ${Object.keys(assets).length}. Tag replacement preserves the stable asset ID (see Scenario Tests \/ Logic Tests).<\/p>\n    <h3>Tag replacement (demo)<\/h3><select id=\"tr\">${Object.keys(assets).slice(0,14).map(i=>`<option>${i}<\/option>`).join(\"\")}<\/select>\n    <button class=\"act\" onclick=\"doReplace()\">Replace tag (keep asset ID)<\/button><div id=\"trres\"><\/div><\/div>`;\n  }\n  else if(tab===\"Event Log\"){\n    m.innerHTML=`<div class=\"card\"><h2>Append-only event log (latest 40)<\/h2>\n    <table><tr><th>Event<\/th><th>Type<\/th><th>Asset<\/th><th>Site<\/th><th>Source<\/th><th>Observed<\/th><th>Idem key<\/th><\/tr>\n    ${events.slice(-40).reverse().map(e=>`<tr><td>${e.eventId}<\/td><td>${e.type}<\/td><td>${e.assetId||\"\u2014\"}<\/td><td>${e.site||\"\u2014\"}<\/td><td>${e.src}${e.offline?\" <span class='pill y'>OFFLINE<\/span>\":\"\"}<\/td><td>${(e.observedAt||e.ingestedAt).slice(11,19)}<\/td><td style=\"font-family:monospace\">${e.idemKey}<\/td><\/tr>`).join(\"\")}<\/table><\/div>`;\n  }\n  else if(tab===\"Scenario Tests\"){ renderScenarioTests(); }\n  else if(tab===\"Logic Tests\"){ renderLogicTests(); }\n}\n\n\/* guided E2E *\/\nlet e2eSteps=[];\nfunction runGuidedE2E(){\n  resetDemoSilent(); e2eSteps=[]; tab=\"Guided Walkthrough\"; renderNav();\n  const L=s=>{e2eSteps.push(s); const d=$(\"#e2e\"); if(d) d.innerHTML=e2eSteps.join(\"\\n\");};\n  L(\"STEP 0  Seed: 24 bins commissioned @ Warehouse WH1 (available for redeployment).\");\n  \/\/ delivery trip WH -> SA(6) -> SB(6)\n  const aDeliver=Object.keys(assets).filter(id=>assets[id].confirmedSite===SITES.WH).slice(0,6);\n  const bDeliver=Object.keys(assets).filter(id=>assets[id].confirmedSite===SITES.WH&&!aDeliver.includes(id)).slice(0,6);\n  const dt=createTrip(\"delivery\",[{site:SITES.SA,dir:\"deliver\",items:aDeliver},{site:SITES.SB,dir:\"deliver\",items:bDeliver}]);\n  loadTrip(dt.id);\n  L(`STEP 1  Delivery trip ${dt.id} loaded at WH: ${dt.legs.flatMap(l=>l.items).length} empties onto truck.`);\n  arriveStop(dt.id,0); L(`STEP 2  Truck arrives Store A \u2014 ${aDeliver.length} empties received (custody \u2192 Store A).`);\n  arriveStop(dt.id,1); dt.status=\"COMPLETED\"; L(`STEP 3  Truck arrives Store B \u2014 ${bDeliver.length} empties received (custody \u2192 Store B). Multi-stop trip completed.`);\n  \/\/ fill\n  fillStore(SITES.SA,aDeliver,\"Mixed rigid plastics \u2014 Lot A-1001 (declared)\");\n  fillStore(SITES.SB,bDeliver,\"Aluminum cans \u2014 Lot B-1002 (declared)\");\n  L(`STEP 4  Stores fill: Store A (${aDeliver.length}) + Store B (${bDeliver.length}) declare contents (asset \u2260 contents).`);\n  \/\/ pickup trip A -> B -> WH\n  const pt=createTrip(\"pickup\",[{site:SITES.SA,dir:\"pickup\",items:aDeliver},{site:SITES.SB,dir:\"pickup\",items:bDeliver}]);\n  loadTrip(pt.id);\n  L(`STEP 5  Pickup trip ${pt.id}: truck collects fulls at Store A then Store B (multi-stop). ${pt.legs.flatMap(l=>l.items).length} bins in transit.`);\n  const rec=receiveAtWH(pt.id, pt.legs.flatMap(l=>l.items));\n  L(`STEP 6  Warehouse receipt ${pt.id}: reconciled. Missing ${rec.missing.length}, extra ${rec.extra.length}.`);\n  \/\/ empty + inspect\n  const all=[...aDeliver,...bDeliver];\n  emptyReturn(all, SITES.WH); inspect(all);\n  L(`STEP 7  Empty + inspect @ WH: contents cleared, assets pass inspection, custody \u2192 WH (available for redeployment).`);\n  const c=inventoryConsistency();\n  L(`STEP 8  Inventory consistency: ${c.ok?\"PASS \u2014 all \"+c.total+\" assets reconciled to one custody site\":(\"FAIL: \"+c.issues.join(\"; \"))}.`);\n  save(); render();\n}\nfunction resetDemoSilent(){ freshState(); }\n\n\/* manual UI helpers *\/\nfunction mkDelivery(){\n  const na=parseInt($(\"#dsa\").value), nb=parseInt($(\"#dsb\").value);\n  const wh=Object.keys(assets).filter(id=>assets[id].confirmedSite===SITES.WH&&!assets[id].contents);\n  const a=wh.slice(0,na), b=wh.slice(na,na+nb);\n  const t=createTrip(\"delivery\",[{site:SITES.SA,dir:\"deliver\",items:a},{site:SITES.SB,dir:\"deliver\",items:b}]);\n  $(\"#mkd\").innerHTML=`<p>\u2714 Created <b>${t.id}<\/b>: deliver ${a.length}\u2192Store A, ${b.length}\u2192Store B. Load it next.<\/p>`; save(); render();\n}\nfunction loadTripUI(id){const loaded=loadTrip(id); $(\"#tripres\").innerHTML=`<p>\u2714 ${loaded.length} dispatch reads ingested for <b>${id}<\/b>. Use \"Arrive next stop\".<\/p>`; t_legs_at(id); save(); render();}\nfunction t_legs_at(id){const t=trips.find(x=>x.id===id); if(t._at===undefined)t._at=0;}\nfunction arriveNext(id){const t=trips.find(x=>x.id===id); t_legs_at(id); if(t._at>=t.legs.length){$(\"#tripres\").innerHTML=\"<p>All stops arrived.<\/p>\";return;} const done=arriveStop(id,t._at); t._at++; if(t._at>=t.legs.length) t.status=\"COMPLETED\"; $(\"#tripres\").innerHTML=`<p>\u2714 Stop ${t._at} @ ${t.legs[t._at-1].site}: ${done.length} bins. ${t._at<t.legs.length?\"Next: \"+t.legs[t._at].site:\"Trip COMPLETED.\"}<\/p>`; save(); render();}\nfunction receiveUI(full){const id=$(\"#rt\").value; const t=trips.find(x=>x.id===id); let scanned=t.legs.flatMap(l=>l.items); if(!full) scanned=scanned.slice(0,-1); const rec=receiveAtWH(id,scanned);\n  $(\"#rcres\").innerHTML=`<table><tr><th>Result<\/th><th>Detail<\/th><\/tr><tr><td>Received<\/td><td>${scanned.join(\", \")||\"\u2014\"}<\/td><\/tr><tr><td>Missing<\/td><td style=\"color:${rec.missing.length?'#c62828':'#2e7d32'}\">${rec.missing.join(\", \")||\"none\"}<\/td><\/tr><tr><td>Extra<\/td><td style=\"color:${rec.extra.length?'#c62828':'#2e7d32'}\">${rec.extra.join(\", \")||\"none\"}<\/td><\/tr><tr><td>Status<\/td><td>${pill(t.status)}<\/td><\/tr><\/table>`; save(); render();}\nfunction fillStores(){const sa=Object.keys(assets).filter(id=>assets[id].confirmedSite===SITES.SA); const sb=Object.keys(assets).filter(id=>assets[id].confirmedSite===SITES.SB);\n  fillStore(SITES.SA,sa,\"Mixed rigid plastics \u2014 Lot A-1001 (declared)\"); fillStore(SITES.SB,sb,\"Aluminum cans \u2014 Lot B-1002 (declared)\");\n  $(\"#fillres\").innerHTML=`<p>\u2714 Filled ${sa.length} @ Store A, ${sb.length} @ Store B (declared contents only).<\/p>`; save(); render();}\nfunction mkPickup(){const sa=Object.keys(assets).filter(id=>assets[id].confirmedSite===SITES.SA); const sb=Object.keys(assets).filter(id=>assets[id].confirmedSite===SITES.SB);\n  const t=createTrip(\"pickup\",[{site:SITES.SA,dir:\"pickup\",items:sa},{site:SITES.SB,dir:\"pickup\",items:sb}]); loadTrip(t.id);\n  $(\"#fillres\").innerHTML+=`<p>\u2714 Pickup trip <b>${t.id}<\/b> created & loaded: collect ${sa.length} @ A, ${sb.length} @ B \u2192 WH.<\/p>`; save(); render();}\nfunction emptyInspect(){const full=Object.keys(assets).filter(id=>assets[id].confirmedSite===SITES.WH&&assets[id].contents); emptyReturn(full,SITES.WH); inspect(full);\n  $(\"#erres\").innerHTML=`<p>\u2714 ${full.length} bins emptied + inspected @ WH \u2192 available for redeployment. Asset ID\/history retained; contents cleared.<\/p>`; save(); render();}\nfunction resolveEx(id){const e=exceptions.find(x=>x.id===id); e.resolved=true; confirmLocation(e.assetId,assets[e.assetId].lastSite); render();}\nfunction doReplace(){const id=$(\"#tr\").value; const r=replaceTag(id); $(\"#trres\").innerHTML=`<p>\u2714 ${id}: ${r.old} \u2192 <b>${r.nepc}<\/b>. Asset ID unchanged.<\/p>`; save(); render();}\n\n\/* ================= SCENARIO TESTS (browser-driven; exercises real UI functions) ================= *\/\nlet scenarioResults=null;\nfunction runScenarioTests(){\n  const R=[]; const rec=(name,action,expected,actual,pass)=>R.push({name,action,expected,actual,pass});\n  \/\/ S1 partial receipt\n  freshState(); const t1=createTrip(\"pickup\",[{site:SITES.SA,dir:\"pickup\",items:[\"AST-001\",\"AST-002\",\"AST-003\"]}]); loadTrip(t1.id);\n  const full=t1.legs.flatMap(l=>l.items); const partial=full.slice(0,-1); const rec1=receiveAtWH(t1.id,partial);\n  rec(\"S1\",\"Partial WH receipt (3 expected, 2 scanned)\",\"1 missing \u2192 EXCEPTION, no phantom asset\",`missing=${rec1.missing.length}, status=${t1.status}, assets=${Object.keys(assets).length}`, rec1.missing.length===1&&t1.status===\"EXCEPTION\"&&Object.keys(assets).length===24);\n  \/\/ S2 wrong-location scan\n  freshState(); ingest(\"RECEIPT\",\"AST-004\",assets[\"AST-004\"].epcs[0],SITES.SA,\"portal\",\"OP-03\",\"wloc-1\");\n  const r2=ingest(\"RECEIPT\",\"AST-004\",assets[\"AST-004\"].epcs[0],SITES.SB,\"portal\",\"OP-03\",\"wloc-2\");\n  const ex2=exceptions.find(e=>e.assetId===\"AST-004\"&&e.kind===\"CONFLICTING_OBSERVATION\");\n  rec(\"S2\",\"Wrong-location scan (read @ Store B while @ Store A)\",\"CONFLICT, both events kept, custody unconfirmed\",`status=${r2.status}, exceptions=${exceptions.length}, evKept=${events.filter(e=>e.assetId===\"AST-004\").length}`, r2.status===\"CONFLICT\"&&!!ex2&&events.filter(e=>e.assetId===\"AST-004\").length>=2);\n  \/\/ S3 duplicate read (idempotency)\n  freshState(); const before=events.length; const r3a=ingest(\"MOVE\",\"AST-005\",\"x\",SITES.SA,\"manual\",\"OP-09\",\"dup-K\"); const r3b=ingest(\"MOVE\",\"AST-005\",\"x\",SITES.SA,\"manual\",\"OP-09\",\"dup-K\");\n  rec(\"S3\",\"Duplicate read (same idempotency key)\",\"Ignored, no extra event, no extra asset\",`a=${r3a.status}, b=${r3b.status}, eventsDelta=${events.length-before}, assets=${Object.keys(assets).length}`, r3a.status===\"OK\"&&r3b.status===\"DUPLICATE_IDEMPOTENCY\"&&events.length-before===1&&Object.keys(assets).length===24);\n  \/\/ S4 offline replay\n  freshState(); const q=[[\"off-1\",\"MOVE\"],[\"off-2\",\"MOVE\"],[\"off-1\",\"MOVE\"]]; const seen=[]; for(const [k,ty] of q){ seen.push(ingest(ty,\"AST-006\",\"x\",SITES.SA,\"manual\",\"OP-09\",k,true).status); }\n  rec(\"S4\",\"Offline replay (queued, 1 duplicate)\",\"Order preserved, duplicate suppressed, no phantom\",`seen=[${seen.join(\",\")}], assets=${Object.keys(assets).length}`, seen[2]===\"DUPLICATE_IDEMPOTENCY\"&&Object.keys(assets).length===24);\n  \/\/ S5 tag replacement\n  freshState(); const rr=replaceTag(\"AST-007\"); const after=ingest(\"MOVE\",\"AST-007\",rr.nepc,SITES.SA,\"manual\",\"OP-09\",\"tag-K\");\n  rec(\"S5\",\"Tag replacement\",\"Asset ID stable, old retired, new read maps to same asset\",`old=${rr.old}, new=${rr.nepc}, oldStatus=${tags[rr.old].status}, newRead=${after.status}, assets=${Object.keys(assets).length}`, assets[\"AST-007\"].epcs.includes(rr.nepc)&&tags[rr.old].status===\"retired\"&&after.status===\"OK\"&&Object.keys(assets).length===24);\n  \/\/ S6 inventory consistency after full cycle\n  freshState(); const a=Object.keys(assets).filter(id=>assets[id].confirmedSite===SITES.WH).slice(0,6); const b=Object.keys(assets).filter(id=>assets[id].confirmedSite===SITES.WH&&!a.includes(id)).slice(0,6);\n  const dt2=createTrip(\"delivery\",[{site:SITES.SA,dir:\"deliver\",items:a},{site:SITES.SB,dir:\"deliver\",items:b}]); loadTrip(dt2.id); arriveStop(dt2.id,0); arriveStop(dt2.id,1);\n  fillStore(SITES.SA,a,\"Lot X\"); fillStore(SITES.SB,b,\"Lot Y\");\n  const pt2=createTrip(\"pickup\",[{site:SITES.SA,dir:\"pickup\",items:a},{site:SITES.SB,dir:\"pickup\",items:b}]); loadTrip(pt2.id); receiveAtWH(pt2.id,pt2.legs.flatMap(l=>l.items));\n  emptyReturn([...a,...b],SITES.WH); inspect([...a,...b]); const c=inventoryConsistency();\n  rec(\"S6\",\"Inventory consistency after full cycle\",\"All 24 reconcile to one custody site, no phantom, totals match\",`ok=${c.ok}, total=${c.total}, issues=${c.issues.length}`, c.ok&&c.total===24);\n  scenarioResults=R; return R;\n}\nfunction renderScenarioTests(){\n  const m=$(\"#main\");\n  m.innerHTML=`<div class=\"card\"><h2>Scenario tests \u2014 browser-driven (exercise the real UI functions)<\/h2>\n  <p>These run against the live model in your browser and render the action \/ expected \/ actual \/ pass-fail table below. Differs from \"Logic Tests\", which are code-level assertions.<\/p>\n  <button class=\"act\" onclick=\"runScenarioTests();renderScenarioTable();\">Run scenario tests<\/button>\n  <div id=\"scen\">${scenarioResults?scenarioTable(scenarioResults):\"<p class='note'>Not yet run this session.<\/p>\"}<\/div><\/div>`;\n}\nfunction scenarioTable(R){\n  const pass=R.filter(r=>r.pass).length;\n  return `<table><tr><th>ID<\/th><th>Action<\/th><th>Expected<\/th><th>Actual<\/th><th>Result<\/th><\/tr>\n  ${R.map(r=>`<tr><td><b>${r.name}<\/b><\/td><td>${r.action}<\/td><td>${r.expected}<\/td><td>${r.actual}<\/td><td class=\"${r.pass?'p-ok':'p-fail'}\">${r.pass?\"PASS\":\"FAIL\"}<\/td><\/tr>`).join(\"\")}\n  <tr><td colspan=\"4\"><b>TOTAL: ${pass}\/${R.length} passed (browser-driven)<\/b><\/td><td class=\"${pass===R.length?'p-ok':'p-fail'}\">${pass===R.length?\"ALL PASS\":\"FAILURES\"}<\/td><\/tr><\/table>`;\n}\nfunction renderScenarioTable(){ document.getElementById(\"scen\").innerHTML=scenarioTable(scenarioResults); }\n\n\/* ================= LOGIC TEST SUITE (code-level assertions) ================= *\/\nlet lastResults=null;\nfunction runTests(){\n  const R=[]; const t=(name,fn)=>{try{fn();R.push([name,\"PASS\",\"\"]);}catch(e){R.push([name,\"FAIL\",e.message]);}};\n  const fresh=()=>{freshState();};\n  t(\"T1 Commissioning creates unique asset + tag mapping\",()=>{fresh(); if(Object.keys(assets).length!==24) throw Error(\"count\"); if(tags[assets[\"AST-001\"].epcs[0]].assetId!==\"AST-001\") throw Error(\"mapping\");});\n  t(\"T2 Idempotency: duplicate idemKey ignored\",()=>{fresh(); const n=events.length; ingest(\"MOVE\",\"AST-001\",\"x\",SITES.WH,\"manual\",\"OP-09\",\"K1\"); const r=ingest(\"MOVE\",\"AST-001\",\"x\",SITES.WH,\"manual\",\"OP-09\",\"K1\"); if(r.status!==\"DUPLICATE_IDEMPOTENCY\") throw Error(r.status); if(events.length!==n+1) throw Error(\"dup appended\");});\n  t(\"T3 Dedup burst: same asset+site within 60s suppressed\",()=>{fresh(); ingest(\"MOVE\",\"AST-002\",\"x\",SITES.WH,\"manual\",\"OP-09\",\"KA\"); const r2=ingest(\"MOVE\",\"AST-002\",\"x\",SITES.WH,\"manual\",\"OP-09\",\"KB\"); if(r2.status!==\"DEDUPED_BURST\") throw Error(r2.status);});\n  t(\"T4 Dispatch\u2192Receipt ordering preserved (multi-stop)\",()=>{fresh(); const a=Object.keys(assets).filter(id=>assets[id].confirmedSite===SITES.WH).slice(0,3); const tt=createTrip(\"delivery\",[{site:SITES.SA,dir:\"deliver\",items:a}]); loadTrip(tt.id); arriveStop(tt.id,0); const seq=events.filter(e=>e.assetId===a[0]&&(e.type===\"DISPATCH\"||e.type===\"RECEIPT\")).map(e=>e.eventId); if(!(seq[0]<seq[1])) throw Error(\"order\");});\n  t(\"T5 Partial receipt \u2192 EXCEPTION, no phantom asset\",()=>{fresh(); const tt=createTrip(\"pickup\",[{site:SITES.SA,dir:\"pickup\",items:[\"AST-005\",\"AST-006\"]}]); loadTrip(tt.id); const rec=receiveAtWH(tt.id,[\"AST-005\"]); if(rec.missing.length!==1||tt.status!==\"EXCEPTION\"||Object.keys(assets).length!==24) throw Error(\"mismatch\");});\n  t(\"T6 Extra unmanifested bin detected\",()=>{fresh(); const tt=createTrip(\"pickup\",[{site:SITES.SA,dir:\"pickup\",items:[\"AST-008\"]}]); loadTrip(tt.id); const rec=receiveAtWH(tt.id,[\"AST-008\",\"AST-009\"]); if(rec.extra.length!==1) throw Error(\"extra\");});\n  t(\"T7 Asset\/contents separation\",()=>{fresh(); ingest(\"MOVE\",\"AST-010\",\"x\",SITES.WH,\"manual\",\"OP-09\",\"KC\"); if(assets[\"AST-010\"].contents!==null) throw Error(\"read set contents\"); const tt=createTrip(\"delivery\",[{site:SITES.SA,dir:\"deliver\",items:[\"AST-010\"]}]); loadTrip(tt.id); arriveStop(tt.id,0); fillStore(SITES.SA,[\"AST-010\"],\"glass\"); if(assets[\"AST-010\"].contents!==\"glass\") throw Error(\"declared not linked\"); emptyReturn([\"AST-010\"],SITES.WH); if(assets[\"AST-010\"].contents!==null) throw Error(\"not cleared\");});\n  t(\"T8 Tag replacement preserves stable asset ID\",()=>{fresh(); const r=replaceTag(\"AST-011\"); if(!assets[\"AST-011\"].epcs.includes(r.nepc)) throw Error(\"new epc\"); if(tags[r.old].status!==\"retired\") throw Error(\"old not retired\"); const rr=ingest(\"MOVE\",\"AST-011\",r.nepc,SITES.WH,\"manual\",\"OP-09\",\"KD\"); if(rr.status!==\"OK\") throw Error(rr.status);});\n  t(\"T9 Truck height: 2\u00d7810 feasible nominal; 2\u00d71000 bodies = full clearance, +lid exceeds\",()=>{const sh=stackHeight(2); if(sh.perStack810>TRUCK.clearHeight) throw Error(\"810\"); if(!\/DO NOT CLAIM|EXCEEDS\/.test(sh.verdict1000)) throw Error(\"1000 not flagged\");});\n  t(\"T10 Conflicting ground-site reads \u2192 exception, both events kept\",()=>{fresh(); ingest(\"RECEIPT\",\"AST-012\",assets[\"AST-012\"].epcs[0],SITES.SA,\"portal\",\"OP-03\",\"KF1\"); const r=ingest(\"RECEIPT\",\"AST-012\",assets[\"AST-012\"].epcs[0],SITES.SB,\"portal\",\"OP-03\",\"KF2\"); if(r.status!==\"CONFLICT\") throw Error(r.status); if(events.filter(e=>e.assetId===\"AST-012\").length<2) throw Error(\"dropped\");});\n  t(\"T11 Offline replay: order kept, dup suppressed\",()=>{fresh(); const q=[[\"KG1\",\"MOVE\"],[\"KG2\",\"MOVE\"],[\"KG1\",\"MOVE\"]]; const seen=[]; for(const [k,ty] of q){ seen.push(ingest(ty,\"AST-013\",\"x\",SITES.WH,\"manual\",\"OP-09\",k,true).status); } if(seen[2]!==\"DUPLICATE_IDEMPOTENCY\") throw Error(\"replay dedup\");});\n  t(\"T12 Append-only log (no deletes\/mutation)\",()=>{fresh(); const before=JSON.stringify(events.map(e=>e.eventId)); if(JSON.stringify(events.map(e=>e.eventId))!==before) throw Error(\"mutated\");});\n  t(\"T13 Delayed read cannot silently reverse confirmed custody\",()=>{fresh(); const tt=createTrip(\"pickup\",[{site:SITES.SA,dir:\"pickup\",items:[\"AST-014\"]}]); loadTrip(tt.id); receiveAtWH(tt.id,[\"AST-014\"]); if(assets[\"AST-014\"].confirmedSite!==SITES.WH) throw Error(\"not WH\"); const r=ingest(\"RECEIPT\",\"AST-014\",assets[\"AST-014\"].epcs[0],SITES.SA,\"portal\",\"OP-03\",\"delay-K\"); if(assets[\"AST-014\"].confirmedSite!==SITES.WH) throw Error(\"reversed\"); if(r.status!==\"CONFLICT\") throw Error(\"no conflict:\"+r.status);});\n  t(\"T14 Inventory consistency guard\",()=>{fresh(); const c=inventoryConsistency(); if(!c.ok||c.total!==24) throw Error(\"inconsistent\");});\n  lastResults=R; return R;\n}\nfunction renderLogicTests(){\n  const m=$(\"#main\");\n  m.innerHTML=`<div class=\"card\"><h2>Logic test suite (code-level assertions)<\/h2>\n  <button class=\"act\" onclick=\"runAndShow()\">Run logic tests<\/button>\n  <div id=\"ltres\">${lastResults?logicTable(lastResults):\"<p class='note'>Not yet run this session.<\/p>\"}<\/div>\n  <p class=\"note\">Covers: uniqueness, idempotency, burst dedup, multi-stop ordering, partial\/extra reconciliation, asset-vs-contents, tag replacement, truck height, conflict exceptions, offline replay, append-only, delayed-read custody protection, consistency guard.<\/p><\/div>`;\n}\nfunction logicTable(R){const pass=R.filter(r=>r[1]===\"PASS\").length; return `<table><tr><th><\/th><th>Test<\/th><th>Result<\/th><th>Detail<\/th><\/tr>${R.map(r=>`<tr class=\"testrow\"><td class=\"${r[1]==='PASS'?'p-ok':'p-fail'}\">${r[1]===\"PASS\"?\"\u2714\":\"\u2718\"}<\/td><td>${r[0]}<\/td><td class=\"${r[1]==='PASS'?'p-ok':'p-fail'}\">${r[1]}<\/td><td>${r[2]}<\/td><\/tr>`).join(\"\")}<tr><td colspan=\"2\"><b>TOTAL: ${pass}\/${R.length} passed<\/b><\/td><td colspan=\"2\">${pill(pass===R.length?\"ALL PASS\":\"FAILURES\")}<\/td><\/tr><\/table>`;}\nfunction runAndShow(){const R=runTests(); const d=document.getElementById(\"ltres\"); if(d) d.innerHTML=logicTable(R);}\n\n\/* init *\/\nif(!load()) freshState();\nrenderNav(); render();\n<\/script>\n\n","protected":false},"excerpt":{"rendered":"<p>\u2190 Fargo Techs home \u00b7 Visual journey Returnable Container Traceability \u2014 Closed-Loop Demo SYNTHETIC DATA \u00b7 SIMULATED HARDWARE \u00b7 INTERACTIVE [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_canvas","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"class_list":["post-10004","page","type-page","status-publish","hentry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Operational Dashboard - Fargo Techs Inc.<\/title>\n<meta name=\"description\" content=\"Reusable container traceability for recycling depots, transport and warehouses. Explore Fargo Techs workflows, animations and an illustrative operational demo.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/fargotechs.com\/?page_id=10004\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Operational Dashboard - Fargo Techs Inc.\" \/>\n<meta property=\"og:description\" content=\"Reusable container traceability for recycling depots, transport and warehouses. Explore Fargo Techs workflows, animations and an illustrative operational demo.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/fargotechs.com\/?page_id=10004\" \/>\n<meta property=\"og:site_name\" content=\"Fargo Techs Inc.\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/fargotechs.com\\\/?page_id=10004\",\"url\":\"https:\\\/\\\/fargotechs.com\\\/?page_id=10004\",\"name\":\"Operational Dashboard - Fargo Techs Inc.\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/fargotechs.com\\\/#website\"},\"datePublished\":\"2026-09-24T20:50:00+00:00\",\"description\":\"Reusable container traceability for recycling depots, transport and warehouses. Explore Fargo Techs workflows, animations and an illustrative operational demo.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/fargotechs.com\\\/?page_id=10004#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/fargotechs.com\\\/?page_id=10004\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/fargotechs.com\\\/?page_id=10004#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/fargotechs.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Operational Dashboard\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/fargotechs.com\\\/#website\",\"url\":\"https:\\\/\\\/fargotechs.com\\\/\",\"name\":\"Fargo Techs Inc.\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/fargotechs.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Operational Dashboard - Fargo Techs Inc.","description":"Reusable container traceability for recycling depots, transport and warehouses. Explore Fargo Techs workflows, animations and an illustrative operational demo.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/fargotechs.com\/?page_id=10004","og_locale":"en_US","og_type":"article","og_title":"Operational Dashboard - Fargo Techs Inc.","og_description":"Reusable container traceability for recycling depots, transport and warehouses. Explore Fargo Techs workflows, animations and an illustrative operational demo.","og_url":"https:\/\/fargotechs.com\/?page_id=10004","og_site_name":"Fargo Techs Inc.","twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/fargotechs.com\/?page_id=10004","url":"https:\/\/fargotechs.com\/?page_id=10004","name":"Operational Dashboard - Fargo Techs Inc.","isPartOf":{"@id":"https:\/\/fargotechs.com\/#website"},"datePublished":"2026-09-24T20:50:00+00:00","description":"Reusable container traceability for recycling depots, transport and warehouses. Explore Fargo Techs workflows, animations and an illustrative operational demo.","breadcrumb":{"@id":"https:\/\/fargotechs.com\/?page_id=10004#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/fargotechs.com\/?page_id=10004"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/fargotechs.com\/?page_id=10004#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/fargotechs.com\/"},{"@type":"ListItem","position":2,"name":"Operational Dashboard"}]},{"@type":"WebSite","@id":"https:\/\/fargotechs.com\/#website","url":"https:\/\/fargotechs.com\/","name":"Fargo Techs Inc.","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/fargotechs.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"}]}},"_links":{"self":[{"href":"https:\/\/fargotechs.com\/index.php?rest_route=\/wp\/v2\/pages\/10004","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fargotechs.com\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/fargotechs.com\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/fargotechs.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fargotechs.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=10004"}],"version-history":[{"count":0,"href":"https:\/\/fargotechs.com\/index.php?rest_route=\/wp\/v2\/pages\/10004\/revisions"}],"wp:attachment":[{"href":"https:\/\/fargotechs.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=10004"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}