DI System Incidents
INCIDENT #009 — Nine Days of Zero Fills: Order Size Violated Contract Lot Size
Date: 2026-08-15 · Severity: Critical · Status: Fixed (10e5e9c + ae27754)
Symptom: hrscan v6 live strategy ran 9 days (Aug 6-15) with zero filled orders. All 97 trade records were rejected orders. SUSHI logged "All operations failed" 82 times; BNB entries printed as success while no order existed on OKX.
Root Cause: Three stacked execution bugs: (1) order size not floored to contract lotSz — SUSHI/WIF lotSz=1 rejects fractional sizes, SOL lotSz=0.01 masked the bug; (2) OKX rejection reason lives in data[0].sMsg while top-level msg is empty — code printed "OK" for rejections (retroactively reframes INCIDENT #007's "12 successful BNB orders" as 12 mislabeled rejections); (3) trade log written unconditionally — rejected orders became phantom OPEN positions.
Fix: 10e5e9c: per-coin lot_sz + size floor, sMsg passthrough, success-only trade log, wrapper py_compile gate restored. ae27754: reconciler skips rejected records; 97 phantom entries backfilled rejected=True; ledger reset to honest zero.
Lesson: Log "success" ≠ order exists. orders-history is ground truth for fills. A system can look perfectly healthy while the execution layer is 100% dead — inspection must cross-check trade records against orders-history.
Details: 009-zero-fill-execution-bugs.md
INCIDENT #008 — Silent Daemon Failure & Monitoring Blind Spots
Date: 2026-08-15 · Severity: Critical · Status: Fixed
Symptom: Factory shadow bot offline 9 days undetected; heartbeat showed stale state as live. Second finding: breakout20 TIME_STOP unreachable (bars_held hardcoded 0) — worker alive but position could never time out. Third: control_api monitoring a retired system (config drift).
Root Cause: (1) Malformed systemd unit (semicolon-packed directives) — every restart failed silently. (2) Execution-correctness bug: exit call hardcoded bars_held=0. (3) Monitor target not repointed after system replacement.
Fix: Controlled unit rewrite (backup + diff + reload), TIME_STOP derives real bars held from entry time (6/6 tests pass), di_pulse upgraded to full-chain liveness (HK 2/11 → 11/11 components via monitor_targets.yaml), shadow_heartbeat bridged to control_api (health 0 → 100).
Lesson: Process alive ≠ behavior correct. Monitoring must verify output freshness, not file existence.
Details: 008-silent-daemon-failure.md
Every failure is public. Every fix is proven. This is the Trust Layer.
INCIDENT #007 — Minimum Equity Gate Blocks All Trading
Date: 2026-08-11 · Severity: Critical · Status: Fixed (d53951f)
Symptom: Every scan printed SKIP: equity $70.4 < $500 minimum. Strategy completely stopped for ~30 minutes.
Root Cause: get_eq() read det['eq'] filtered by ccy == 'USDT', returning USDT balance ($70) instead of totalEq ($525). The $500 minimum equity gate then blocked all scans.
Fix: Changed get_eq() to read d['totalEq'] from the balance response, which correctly returns total account value across all currencies.
Lesson: Per-currency equity != total equity in multi-currency accounts. Always use the aggregate field for gating decisions.
INCIDENT #006 — SUSHI Order Rejection Loop (×10)
Date: 2026-08-10 · Severity: High · Status: Fixed (471b186)
Symptom: SUSHI-USDT-SWAP LONG triggered 10 times in 30 minutes (18:51-19:19 UTC). Every order returned "All operations failed" from OKX.
Root Cause: OKX rejected the orders (transient issue — same orders succeeded in later testing). Since no position was created, get_positions() correctly returned empty, and the next minute's scan triggered again. Unlike INCIDENT #005, this was NOT a positions API failure — it was a legitimate order rejection followed by an infinite retry loop.
Fix: Added 30-minute signal cooldown per symbol+direction after a failed order. Cooldown state persisted to hrscan_cooldown.json.
Lesson: Order rejection ≠ position detection failure. Two different bugs with similar symptoms require two different fixes. Every failure path needs its own guard.
INCIDENT #005 — BNB Duplicate Orders (×12)
Date: 2026-08-06 · Severity: Critical · Status: Fixed (f5e4b45)
Symptom: BNB-USDT-SWAP LONG opened 12 times in 12 minutes (07:34-07:45 UTC). All orders succeeded, creating 12 duplicate positions.
Root Cause: get_positions() had a bare except: pass that silently returned {} on ANY API failure (network error, rate limit, non-zero response code). The position dedup check then saw zero positions and allowed the same signal to execute repeatedly.
Fix: Added 3-retry loop with 1-second intervals. On persistent failure, returns None instead of {}, causing the entire scan to skip (fail-safe). Each failed attempt now logs the error code and message.
Lesson: Silent failure modes are the most dangerous bugs in autonomous systems. Every API call needs explicit error handling. except: pass is a liability in production trading code.
INCIDENT #004 — Heartbeat Writer Silent Death
Date: 2026-08-08 · Severity: Medium · Status: Fixed
Symptom: di_heartbeat.json stopped updating on Aug 5. Went undetected for 3 days. No alert triggered.
Root Cause: di_pulse.py was killed during system cleanup but not re-added to crontab. The old daemon monitoring list was stale (monitoring v5 daemons that were already killed).
Fix: Updated daemon list to v6.1 reality. Added di_pulse.py to crontab. Added hrscan v6 cron status check.
Lesson: Monitoring infrastructure needs its own monitoring. A dead heartbeat writer is a silent failure — the system appears healthy because no alert fires.
INCIDENT #003 — verify_push Hangs on GitHub CDN
Date: 2026-08-08 · Severity: Low · Status: Fixed
Symptom: verify_push.sh never completed. Log file always empty. Daily report push verification was blind.
Root Cause: Script curled raw.githubusercontent.com from AliCloud (China). GFW blocked the request, causing infinite hang. Cron timeout killed it before any output.
Fix: Replaced remote CDN check with local status file (/root/di-proof-repo/.push_status). gen_artifact.py writes push result; verify_push.sh reads it locally.
Lesson: Don't assume network reachability. Design verification to work within known network constraints.