The tracker is a single-file browser application (~4,600 lines). It has no server; all computation runs client-side. Five subsystems communicate through a shared in-memory DATA store and a persistent IndexedDB (IDB). User inputs flow from planning fields and file uploads into parsers, which populate DATA, which drives every rendered UI surface.
Full system — data flow left → right, feedback right → left
SOR / TMS data path
iGate Hub path
iGate Employee path
CURE path
Planning input path
DATA store output
Rendered UI → coordinator
IDB persistence
02
Data Ingestion Pipeline
All data enters through a single drag-drop handler — onFileDrop() — which classifies the file by name pattern and routes it to the right parser. Every parser is a Promise; once resolved, its output is written directly into the DATA global and the relevant render functions are called.
Per-destination: Pkg Cube, Avg Net, Avg Equip Cap → Util % = (Pkg Cube × Avg Net) / Avg Equip Cap × 100. Rows with TFCS ≥ 95% flagged separately.
File ordering contract: The number in the filename suffix (e.g. Hub Summary (19).xlsx) is the snapshot index — higher = later. Base file (no number) is index 0. _parseFilenameIdx(name) extracts this. The Timeline module uses these indices to build a chronological sort without relying on file-system timestamps.
sortDate source: Always derived from the filename via _inferSortDateFromFile() — never from cell B1 which uses =TODAY() and would be unreliable. Pattern: 2026-05-04 from SOR-US-CHEMA-2026-05-04-T.xlsx.
03
State Computation Layer
Two parallel state aggregators exist: renderHubKpiGrid() computes display-ready metrics for the Hub tab KPI tiles, and _dopState() computes an identical metric set used by the DOP module. Both read the same DATA store and both now route planPPH and planVol through the user-input helpers added in v2.11. The duplication is intentional — the KPI grid renders tiles while _dopState() returns a state object for further computation downstream.
Writes innerHTML of #hub-kpi-grid. 8 tiles: Net Volume, Actual PPH, Paid Day, Cost/Piece, Total Hours, Headcount, Flow/Hour (or Process Rate), % Smalls (with iGate magnitude).
Master DOP refresh. Called on every file upload, every clear, every tab switch to hub, and every 30-second clock tick.
renderIGateScanMetrics()
_igatePerUserRows(), _kpiStripeFor()
Hub tab iGate table: per-belt gross vol, PPH with color bands (red <70 / amber 70–99 / green 100–149 / blue ≥150).
renderVolumeReconciliation()
DATA.sor, DATA.hub
Cross-check table: SOR reported vs iGate LooseOutbound+BagsLinked per belt, delta column, coverage %.
04
KPI Metric Fallback Chains
Every metric has a priority chain: the authoritative source is tried first; if it returns zero or null (which mid-sort SOR exports do for most fields), the next source is used. This means the tracker shows meaningful numbers at every stage of the sort — not just post-sort when TMS finalizes the SOR.
Priority chain for each KPI metric — top = highest priority
05
DOP Module — Pace, Scenarios & Back-Solve
The DOP (Daily Operations Plan) module is the primary operational decision surface. It lives inside the Hub tab and refreshes every 30 seconds via _dopStartTick(). The module's entry point is dopRenderAll(force), which builds a fresh state object and dispatches to four sub-renderers.
DOP module call graph and decision branches
06
Timeline Module — Intra-Sort Snapshot Pipeline
The Timeline tab accepts a bulk upload of all mid-sort snapshot files at once — any combination of Hub Summary (N), Employee Summary (N), and SOR (N) files. The number suffix N is the snapshot index. The pipeline classifies, parses, chronologically orders, and renders them as three Chart.js charts. The critical v2.11 fix: the SOR snapshot's summary object now carries both the full {planned, actual} dict (for KPI grid use) and the flat timeline fields (paidDayActual, sortDownActual, etc.) in a single merged object.
Timeline pipeline — file drop to Chart.js
07
Planning Input Subsystem (v2.11)
Before v2.11 every planPPH reference read directly from SOR's planned['PPH'] — a per-employee target (~217) rather than the building-level Adjusted Building PPH (~119). This corrupted every stripe color, every Cost/Piece plan, every DOP scenario, and every back-solve target. The v2.11 planning input subsystem intercepts all three derivation sites.
Input fields
hub-plan-pph-input — number field, Adj Bldg PPH. Placeholder "e.g. 119". Persists to localStorage['hub_plan_pph'].
hub-plan-vol-input — number field, Plan Volume override. Persists to localStorage['hub_plan_vol'].
Both live above the KPI grid inside the Hub tab. oninput calls hubPlanInputChanged() → re-renders grid + DOP.
Helper functions
_hubPlanPPH() — reads input value; returns number or null.
_hubPlanVol() — reads input value; returns number or null.
_loadHubPlanInputs() — called at DOMContentLoaded, restores localStorage values into inputs.
_suggestHubPlanFromSOR() — on SOR load: if input is empty AND SOR planned PPH is 70–200, pre-fills the input.
Affected callsites
All three state-building functions now route through _hubPlanPPH() for planPPH:
renderHubKpiGrid() line 1789 _dopState() line 3551 _buildSnapshotRecord() line 2172
_hubPlanVol() similarly overrides planVol at all three sites.
08
On-Floor Coordinator Feedback Loop
The tracker is designed around a four-hour sort window (Twilight). The coordinator's interaction has three phases: pre-sort setup, intra-sort monitoring, and post-sort capture. Each phase drives a different subsystem.
Temporal feedback loop — sort day timeline
09
v2.11 Fix Summary
#
Bug
Root cause
Fix (function + line)
1
Flow/Hour KPI tile showed — during intra-sort even though netVol and paidDay were both populated
Guard +actual['Flow Per Hour'] > 0 correctly suppressed SOR's mid-sort 0, but no fallback existed for any sort date, not just today
renderHubKpiGrid(): when SOR actual = 0, derive _processRate = netVol / paidDay. Tile label switches to "Process Rate · Vol ÷ Paid Day".
2
Timeline batch upload: after activating the latest snapshot, Hub KPI tiles showed old/empty values for Flow/Hour, % Smalls, Sort Span
Two bugs: (a) onTlFiles wrote summary: summ where summ was the 4-field flat object from _parseSORSummarySheet, overwriting the full {planned,actual} dict from parseSORStaffing. (b) _activateLatestSnapshot copied rows/hours/empTotals but not DATA.sor.summary or DATA.sor.sortDate.
onTlFiles(): merge both shapes — summary = {planned, actual, ...summ}. _activateLatestSnapshot(): add DATA.sor.summary = latest.sor.summary and DATA.sor.sortDate = latest.sor.sortDate.
3
Back-Solve showed fabricated projections ("305,619 projected · burn 76k pkgs/hr") when old sort data was loaded
_dopRenderPace computed elapsedH from wall-clock time. Old sort data: wall-clock is past sort end → status = 'post' → elapsedH = span.spanH = 4h → burnNow = 305k/4 = 76k pkgs/hr.
_dopRenderPace(): check DATA.sor.sortDate !== today → if true, show static historical summary banner and return early. Also: volume anomaly warning if netVol > planVol × 1.2.
Hard-coded max:5 on the Paid Day Y-axis in renderTimelineCharts().
Compute _pdMax = min(8, max(5, ceil(maxValue × 1.15))) from both actual and planned series. Replace max:5 with suggestedMax: _pdMax.
5
Plan PPH showed 217.6 (per-employee target from SOR) instead of ~119 (Adj Bldg PPH)
All three state-builders read planned['PPH'] directly from SOR Summary, which stores the individual-employee rate, not the building-adjusted rate.
New HTML inputs hub-plan-pph-input + hub-plan-vol-input. Helpers _hubPlanPPH() / _hubPlanVol() inserted at all three planPPH / planVol derivation sites. localStorage persist + DOMContentLoaded restore + SOR auto-suggest.
6
% Smalls showed — mid-sort (SOR actual = 0 until TMS finalizes)
No fallback when SOR actual % Smalls = 0.
Filter DATA.hub.rows for belts in {SLS01,SLS02,SS}, sum LooseOutbound+BagsLinked, divide by netVol. Use _kpiCardMag to show absolute count (big) above percentage (secondary).
Removed in v2.11: Sort Span KPI tile removed from Hub tab. The value is still computed by _dopState() for DOP use, and appears in the Volume Reconciliation table. The tile was redundant alongside the DOP pace panel.