# 🚨 CRITICAL ISSUES DIAGNOSIS & FIX PLAN ## For Tomorrow's Presentation --- ## 📊 ISSUE 1: Availability Starting at 100% Then Dropping ### Root Cause **The calculation is CORRECT, but the time accumulation logic is flawed.** #### How It Works Now: 1. Machine cycles function runs every time it receives input (sensor polls) 2. When `trackingEnabled = true`: - If machine state = 1: adds time to `operatingTime` - If machine state = 0: adds time to `downtime` 3. Availability = operatingTime / (operatingTime + downtime) #### Why It Starts at 100%: - Initially: operatingTime = 10s, downtime = 0s - Availability = 10/10 = 100% ✓ #### Why It Drops to 50%, 40%, etc.: - Machine state = 0 (idle between cycles, or actual stops) - Downtime accumulates: 10s, 20s, 30s... - Availability = 10/(10+30) = 25% ❌ ### The Problem: **Every idle moment (state=0) counts as downtime**, even if it's just waiting for the next cycle. This is technically accurate if you want to track "machine utilization", but NOT accurate for OEE availability. ### Correct OEE Availability Formula: **Availability = Run Time / Planned Production Time** Where: - Run Time = time actually producing (cycles completing) - Planned Production Time = total time MINUS planned stops (breaks, maintenance) ### Current Implementation Error: We're treating ALL state=0 time as downtime, but we should ONLY count: 1. Unplanned stops (machine malfunction, material shortage, etc.) 2. NOT idle time between cycles 3. NOT planned stops (lunch, breaks, maintenance) --- ## 📊 ISSUE 2: START Button Doesn't Affect Work Order Progress ### Root Cause **The START button IS working, but the complex session logic might be interfering.** #### Flow Trace: 1. User clicks START in Home dashboard 2. Home Template sends `{ action: "start" }` 3. Message goes: Home Template → link out 2 → link in 2 → Work Order buttons 4. Work Order buttons case "start" executes 5. Sets `trackingEnabled = true` ✓ 6. Creates new session in database ✓ ### Potential Issues: 1. **Session creation might be failing** (database error silently swallowed) 2. **trackingEnabled is being set, but then immediately cleared** somewhere 3. **Machine cycles isn't receiving proper input** to trigger cycles ### Diagnosis Needed: Check if: - `trackingEnabled` global variable is actually `true` after clicking START - Machine cycles function is being triggered (check debug log) - Cycles are being counted (check `cycleCount` global variable) --- ## 📊 ISSUE 3: Stop Prompt Not Showing ### Root Cause **WIRING ERROR: Stop prompt message not reaching the UI.** #### Current Flow (BROKEN): 1. User clicks STOP 2. Work Order buttons case "stop" executes 3. Sets `msg._mode = "stop-prompt"` 4. Returns on output 2 5. Output 2 is wired to: `f6ad294bc02618c9` (MySQL node) ❌ #### Should Be: 1. User clicks STOP 2. Work Order buttons case "stop" executes 3. Sets `msg._mode = "stop-prompt"` 4. Returns on output 2 5. Output 2 should go to: Stop Reason UI Template ✓ #### Additional Issue: The Stop Reason UI Template (ID: `94afa68639264697`) is wired to output back to Work Order buttons, BUT Work Order buttons output 2 doesn't go to it! **This is a circular dependency that wasn't properly wired:** - STOP button → Work Order buttons → Stop Reason UI → Work Order buttons (with reason) --- ## 🎯 COMPREHENSIVE FIX PLAN ### Priority 1: Fix Stop Prompt (CRITICAL for presentation) **Impact: HIGH | Complexity: LOW | Time: 5 minutes** #### Actions: 1. Add a Switch node after Work Order buttons output 2 2. Route `_mode == "stop-prompt"` to Stop Reason UI 3. Route other messages (refresh, etc.) to existing MySQL node 4. Ensure Stop Reason UI output goes back to Work Order buttons #### Side Effects: - None - this is just fixing broken wiring #### Roadblocks: - None anticipated --- ### Priority 2: Fix Availability Calculation (CRITICAL for presentation) **Impact: HIGH | Complexity: MEDIUM | Time: 15 minutes** #### Option A: Track Only Unplanned Downtime (RECOMMENDED) **Pros:** - Accurate OEE calculation - Planned stops don't affect availability - Aligns with industry standard **Cons:** - Requires stop categorization to work (Priority 1 must be done first) #### Implementation: 1. Modify Machine cycles to NOT accumulate downtime during state=0 2. ONLY accumulate downtime from stop_events where `affects_availability = 1` 3. Query database in KPI calculation: ```javascript // Get unplanned downtime from database const unplannedDowntime = await getUnplannedDowntime(workOrderId); availability = operatingTime / (operatingTime + unplannedDowntime); ``` #### Option B: Ignore State=0 Between Cycles (SIMPLER but less accurate) **Pros:** - Quick fix - No database queries needed **Cons:** - Won't track actual unplanned stops accurately - Defeats the purpose of stop categorization #### Implementation: 1. Remove downtime accumulation from Machine cycles 2. Set availability = 100% while tracking is enabled 3. (Not recommended - loses valuable data) #### Side Effects: - Historical data won't be affected (already in database) - Going forward, availability will be calculated differently #### Roadblocks: - None, but requires database queries (Option A) --- ### Priority 3: Simplify START/STOP Logic (MEDIUM priority) **Impact: MEDIUM | Complexity: LOW | Time: 10 minutes** #### Current Issue: The START/STOP cases have complex session management that might be causing issues. #### Actions: 1. Keep the complex logic BUT add better error handling 2. Add debug logging to track what's happening 3. Ensure `trackingEnabled` is set correctly #### OR (simpler): 1. Strip out session management from START/STOP 2. Make START/STOP ONLY control `trackingEnabled` 3. Move session management to work order start/complete only #### Recommended Approach: **Keep session management, but add safeguards:** ```javascript case "start": { // Simpler version - just enable tracking const now = Date.now(); if (!global.get("productionStartTime")) { global.set("productionStartTime", now); global.set("operatingTime", 0); global.set("downtime", 0); } global.set("trackingEnabled", true); global.set("lastUpdateTime", now); node.warn("[START] Tracking enabled"); return [null, null, null, null, null]; } ``` #### Side Effects: - Sessions won't be created on START/STOP (only on work order start/complete) - Simpler = fewer failure points #### Roadblocks: - None --- ### Priority 4: Fix Work Order Progress Display (LOW priority) **Impact: LOW | Complexity: LOW | Time: 5 minutes** #### Issue: User says "START/STOP made no difference on work order advance" #### Diagnosis: - Work order progress IS updating (you said cycles are counting) - Likely the UI isn't refreshing to show the update #### Actions: 1. Check if cycle updates are reaching "Back to UI" function 2. Verify Home Template is receiving `activeWorkOrder` updates 3. Add forced refresh after each cycle #### Side Effects: - None #### Roadblocks: - None --- ## 🚀 IMPLEMENTATION ORDER FOR TOMORROW ### Phase 1: CRITICAL FIXES (30 minutes) 1. **Fix Stop Prompt Wiring** (5 min) - Add Switch node - Wire stop-prompt to Stop Reason UI 2. **Fix Availability Calculation** (15 min) - Remove downtime accumulation from state=0 - Track downtime only from stop_events - Update KPI calculation to query database 3. **Simplify START/STOP** (10 min) - Remove complex session logic - Just enable/disable tracking ### Phase 2: TESTING (15 minutes) 1. Test stop prompt shows when clicking STOP 2. Test availability stays high (>95%) during normal operation 3. Test START/STOP enables/disables cycle counting 4. Test unplanned stop reduces availability 5. Test planned stop does NOT reduce availability ### Phase 3: VALIDATION (15 minutes) 1. Run full work order from start to finish 2. Verify KPIs are accurate 3. Document any remaining issues --- ## 📋 DETAILED FIX SCRIPTS ### Fix 1: Stop Prompt Wiring ```python # Add switch node between Work Order buttons output 2 and destinations # Route stop-prompt to Stop Reason UI # Route others to MySQL ``` ### Fix 2: Availability Calculation ```javascript // In KPI Calculation function: // Query unplanned downtime from database const unplannedDowntimeSql = ` SELECT COALESCE(SUM(duration), 0) as downtime FROM stop_events WHERE work_order_id = '${activeOrder.id}' AND affects_availability = 1 AND resume_time IS NOT NULL; `; // Use this instead of global.get("downtime") ``` ### Fix 3: Simplified START/STOP ```javascript case "start": { const now = Date.now(); if (!global.get("productionStartTime")) { global.set("productionStartTime", now); global.set("operatingTime", 0); global.set("downtime", 0); } global.set("trackingEnabled", true); global.set("lastUpdateTime", now); return [null, null, null, null, null]; } case "stop": { // Show prompt first msg._mode = "stop-prompt"; return [null, msg, null, null, null]; } // Then after prompt response: case "stop-reason": { // Disable tracking after reason selected global.set("trackingEnabled", false); // ... rest of logic } ``` --- ## ⚠️ RISKS & MITIGATION ### Risk 1: Database Queries Slow Down KPI Updates **Mitigation:** Cache downtime value, update every 30 seconds instead of every 5 ### Risk 2: Breaking Existing Functionality **Mitigation:** Create backup before changes, test each fix individually ### Risk 3: Running Out of Time **Mitigation:** Prioritize fixes - do Priority 1 & 2 only if time is short --- ## ✅ SUCCESS CRITERIA FOR TOMORROW 1. **Stop button shows prompt** ✓ 2. **Availability stays >90% during production** ✓ 3. **START button enables cycle counting** ✓ 4. **STOP button disables cycle counting** ✓ 5. **Unplanned stops reduce availability** ✓ 6. **Planned stops do NOT reduce availability** ✓ 7. **Quality affected by scrap** ✓ (already working) 8. **OEE calculated correctly** ✓ --- **Ready to implement? Let's start with Priority 1.**