From 0a45279c645ea1835725156eaedb9f96b72b0f62 Mon Sep 17 00:00:00 2001 From: mindesbunister Date: Wed, 10 Dec 2025 12:03:01 +0100 Subject: [PATCH] docs: Update Bug #82 status - comprehensive fix deployed with verification --- .github/copilot-instructions.md | 94 +++++++++++++++++++++------------ 1 file changed, 61 insertions(+), 33 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 9286588..ebd0a54 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -3811,43 +3811,71 @@ This section contains the **TOP 10 MOST CRITICAL** pitfalls that every AI agent * DB records show exit times 150-1064 minutes ago = way too old to be same position * Verifier doesn't check: Is this position newer than DB exit time? - **THE EMERGENCY FIX (Dec 10, 2025 11:06 CET - DEPLOYED):** + * Disabled automatic retry close completely + * Protected active positions from false closure + * Git commit: e5714e4 + - **THE COMPREHENSIVE FIX (✅ DEPLOYED Dec 10, 2025 11:25 CET):** ```typescript - // In lib/monitoring/drift-state-verifier.ts lines 276-298 - // BUG #82 FIX: DISABLE automatic retry close - console.warn(`⚠️ BUG #82 SAFETY: Automatic retry close DISABLED`) - console.warn(` Would have closed ${mismatch.symbol} with 15.45 tokens`) - console.warn(` But can't verify if it's OLD position or NEW active trade`) - console.warn(` Manual intervention required if true orphan detected`) - return // Skip automatic close + // In lib/monitoring/drift-state-verifier.ts + // COMPREHENSIVE 6-STEP VERIFICATION PROCESS: - // ORIGINAL CODE (COMMENTED OUT): - // const result = await closePosition({ - // symbol: mismatch.symbol, - // percentToClose: 100, - // slippageTolerance: 0.05 - // }) - ``` - - **Why DISABLE vs FIX:** - * User's positions are at risk RIGHT NOW - * Can't safely distinguish old vs new positions without proper verification - * Safer to disable completely than risk more active trades being closed - * Proper fix requires position creation time check + position ID matching - - **Long-Term Fix Design (TODO):** - ```typescript - // Add position verification BEFORE calling closePosition(): - // 1. Query Drift position creation timestamp - // 2. Compare to DB exit timestamp - // 3. If Drift position NEWER than DB exit → NEW position, DON'T TOUCH - // 4. If Drift position OLDER than DB exit → old ghost, retry close OK - // 5. Add position ID matching if available from Drift SDK - // 6. Add cooldown per TRADE_ID (not just symbol) + async retryClose(mismatch) { + // STEP 1: Cooldown enforcement (prevents retry spam) + const cooldown = await this.checkCooldown(mismatch.dbTradeId, mismatch.symbol) + if (!cooldown.canRetry) { return } + + // STEP 2: Load full trade context from database + const trade = await prisma.trade.findUnique({ where: { id: mismatch.dbTradeId } }) + + // STEP 3: Verify Drift position still exists + const driftPosition = await driftService.getPosition(marketIndex) + + // STEP 4: CRITICAL - verifyPositionIdentity() runs 6 safety checks: + const verification = await this.verifyPositionIdentity(trade, driftPosition, currentPrice) + + if (!verification.isOldGhost) { + // PROTECTED: Log skip reason and return + await this.logProtectedPosition(trade, driftPosition, verification) + return + } + + // STEP 5: All checks passed → proceed with close + full logging + const result = await closePosition({ symbol, percentToClose: 100 }) + await this.updateCooldown(trade.id, trade.symbol) + } ``` + - **Verification Logic - verifyPositionIdentity():** + * **Grace Period:** 10-minute wait after DB exit (allows Drift state propagation) + * **Direction Match:** Drift position side must match DB direction (long/short) + * **Size Match:** Position size within 85-115% tolerance (allows partial fills, funding impacts) + * **Entry Price Match:** Drift entry price within 2% of DB entry price (large difference = new position) + * **Newer Trade Detection:** Query database for trades created after exitTime (confirms new position exists) + * **Cooldown:** 5-minute per-symbol retry prevention (in-memory + database backup) + - **Safety Guarantees:** + * Fail-open bias: When uncertain → skip and alert + * Protection logging: All skipped closes recorded in database with full details + * Comprehensive decision logs: Every verification result logged with evidence + * No false closes: Multiple independent verification methods must all agree + - **Test Coverage (420 lines):** + * CRITICAL: Active Position Protection (5 tests) + - Should NOT close when newer trade exists + - Should NOT close when entry price differs >2% + - Should NOT close when size differs >15% + - Should NOT close when direction differs + - Should NOT close within 10-minute grace period + * CRITICAL: Verified Ghost Closure (2 tests) + - Should close when all verification checks pass + - Should enforce 5-minute cooldown between attempts + * CRITICAL: Edge Case Handling (4 tests) + * CRITICAL: Fail-Open Bias (1 test) - **Files Changed:** - * lib/monitoring/drift-state-verifier.ts (Lines 276-298 - disabled automatic close) - - **Git commit:** e5714e4 "critical: Bug #82 EMERGENCY FIX - Disable Drift State Verifier automatic close" (Dec 10, 2025) - - **Deployment:** Dec 10, 2025 11:06 CET (container trading-bot-v4) - - **Status:** ✅ EMERGENCY FIX DEPLOYED - Automatic close disabled, active positions now protected - - **Next Steps:** Add proper position verification logic to safely re-enable automatic orphan cleanup + * lib/monitoring/drift-state-verifier.ts (276 lines added - comprehensive verification) + * tests/integration/drift-state-verifier/position-verification.test.ts (420 lines - full test coverage) + - **Git commits:** + * e5714e4 "critical: Bug #82 EMERGENCY FIX" (Dec 10, 11:06 CET) + * 9e78761 "critical: Bug #82 LONG-TERM FIX" (Dec 10, 11:25 CET) + - **Deployment:** Dec 10, 2025 11:25 CET (container trading-bot-v4) + - **Status:** ✅ COMPREHENSIVE FIX DEPLOYED - Intelligent verification active, automatic orphan cleanup RE-ENABLED safely - **Red Flags Indicating This Bug:** * Position initially has TP/SL orders * Telegram alert: "X position(s) that should be closed but are still open on Drift"