◆ DEEP GUIDE

Swing Deck Deep Guide

The power-user reference. About a 45-minute read top-to-bottom; mostly used as a lookup once you've been around the dashboard a few weeks.

If you haven't read Swing Deck Guide Reference yet, start there. This doc assumes you know what a card looks like, what a trap chip does, and that "the math cleared" is different from "the AI told you to."


Part 1 — How it ticks

1. The five-layer architecture

Swing Deck is a stack. Each layer answers a different question. They run in order; outputs feed downstream.

Layer What it answers Output
L1 — 11-point technical Is the tape worth trading? Composite score 0–100, grade A–F
L2 — 13 risk pillars (E1–E13) Does the math allow this trade? Pass / refuse, per pillar
L3 — 12-point war calibration When VIX > 25, what changes? Tighter caps, defensive overlays
L4 — 13-point options If options are open, is this strategy worth it? Long-call vs spread vs CSP, strike, DTE
AI surfaces (10 coaches) What does this mean? Triggered narration, structured output

The framework refuses. The dashboard narrates. AI explains. You decide. That order is the brand.

2. The audit cycle, every 5 minutes

The daemon (audit_framework.py --watch) runs the cycle on a 5-min interval. One cycle, ~30–90 s for 7–10 tickers:

  1. Macro fetch — VIX, oil ($USD), brent ($USD), ^IRX. Determines war mode (VIX > 25), oil shock (Oil > $100), armor yield warn (^IRX < 4%).
  2. Regime classificationregime_engine resolves the active regime label (OIL_SHOCK, KINETIC, WAR, NORMAL) plus per-sleeve cap overrides.
  3. Per-ticker pass — for each symbol in portfolio.txt + candidates.txt: - Skip if cash armor (USFR/SGOV). - Fetch df_d (daily) + df_w (weekly) from yfinance/Polygon. - compute_daily(df_d) → indicators (EMA stack, RSI, ADX, MACD, ATR, BB, OBV, sweep_clean). - compute_weekly(df_w) → weekly trend + EMA alignment. - detect_catalyst(t) → earnings calendar, headline news, Fed events. - compute_structure(df_d) → primary_S, primary_R, levels_above, levels_below from 10 S/R sources collapsed via 0.15 × ATR confluence merging. - score_11pt(...) → composite, grade, bias, sl_val, tp1/tp2/tp3, rr. - score_12pt_war(...) if war mode. - score_13pt_options(...) if options engine enabled. - compute_composite(...) → final score with regime modifiers. - Pillar gate checks — sleeve caps, sector caps, hard-cash floor, drawdown. - Trap contradiction detection — see below. - Enrichment fetches: insider Form 4, float/short, RS-rank, gamma walls, comparable setups.
  4. System-level rebalance — if portfolio drawdown > 7% (E3) or hard-cash floor breached (E5) or armor yield drops (E12), portfolio_rebalancer writes rotation orders.
  5. Atomic JSON write to audit_output.json. Dashboard polls every 5 s.
  6. Alerts engine detects threshold transitions and emails on state changes (entry-eligible, near-stop, exit-review, etc.).

Heartbeat is written at every step (_write_audit_state) so the dashboard's audit signal can show progress and detect a stalled cycle.

3. Trap contradiction detection — the safety net

After scoring, the framework runs _detect_trap_contradictions(ind_d, ind_w, r11). Trap flags fire when two server-computed signals disagree in ways the methodology calls bagholder traps. Pre-v6.6.9 the framework had ALL the data to surface these but didn't — the user had to mentally reconcile contradictory chips. Trap surfacing is the methodology's "math floor not motivation" job.

Trap flag Fires when Translation
⚠ Trap: chase-the-top Strong weekly trend (ADX-W ≥ 30) AND overbought weekly RSI (≥ 75) Move already happened; you'd pay the top
⚠ Trap: bull-stack distribution Bullish EMA stack but Falling OBV with high vol Price up, smart money out
⚠ Trap: weak rally HH/HL but vol_ratio < 0.7 Rally on no volume — usually fails

Trap chips override the score. If you see one, the framework is refusing the trade even when the gate technically opened. Don't override.


Part 2 — The math

4. Layer 1 — The 11-point technical score

Each cell scores 0–10. Sum = 0–100 (Point 9 is the composite, not a separate scoring cell). Grades: A ≥ 90 · B 80–89 · C 70–79 · D 60–69 · F < 60.

# Cell What it reads
1 Trend Confirmation HH/HL on daily, EMA stack alignment, weekly bonus
2 Momentum & Strength RSI band (40–65 sweet spot), ADX (≥ 30 strong), MACD bullish + hist rising
3 Volatility Context BB width, ATR%, EMA21/price proximity, loose-trend bonus
4 Volume & Flow vol_ratio (today vs 20-day avg), OBV trend, sweep_clean
5 Whale Sentiment MarketAux news + AI confirmation coach output
6 Manipulation Detection Sweeps + OBV + vol confirmation; book-aware penalty (v6.7.43)
7 Trade Execution Price vs EMA21, structure type, entry quality near support
8 Position Sizing Vol-adjusted (0–5) + stop-tightness (0–5); cap-breach floor at conc=2
10 Macro Correlation VIX leg (0–3) + sector trend leg (0–3) + per-ticker RS leg (0–4)
11 Hidden Tape Call/put gamma ratio + put sweep + max-pain magnet + squeeze potential

Modifiers apply after the base sum:

Composite = max(0, min(100, base + modifiers)).

The cells are not equally weighted — they're equally scored. The 11-pt model trusts that a clean signal across cells matters more than any one cell's strength. That's why a single dead cell (e.g. macro at 5) doesn't tank the score, but five mediocre cells will.

5. Layer 2 — The 13 risk pillars (E1–E13)

Pillars 1–7 are baseline (always active). Pillars 8–13 are war-time / regime overlays.

Detailed mechanics per pillar:

E1 — Armor Cap (15% per asset)

Refuses: any single position > 15% of portfolio. Cash positions exempt. Structural — overrides "I'm so sure about this one."

E2 — Stop Discipline (Trade-the-Structure, v6.7.47)

Refuses: holding without a real broker stop. The stop sits at max(primary_S × 0.999, entry − 2×ATR) — tighter of structural support or 2×ATR floor. The 2×ATR floor preserves Pillar 7's spirit; structural support snaps closer when the framework can see real geometry. Mental stops negotiate. Broker stops don't.

E3 — Red-Line (7% portfolio drawdown)

Refuses: holding through a 7% drop from cost-basis high-water mark. Daemon writes 50%-cash pivot orders automatically. Multi-window thresholds added v5.6: today vs prior close ≤ −4%, week peak ≤ −7%, 30-day rolling ≤ −10%.

E4 — Score Gate (composite ≥ 80)

Refuses: new entries on tickers below B-grade (composite < 80). Gate is hard. Most setups don't clear it. By design.

E5 — Pre-Market Firewall (S&P futures −1.5%)

Refuses: new long entries when ES futures down > 1.5% at 7:25 AM MST. Exits and stop-raises still allowed.

E6 — Sector Cap (40% per theme)

Refuses: > 40% in any single sleeve (semis, AI infra, defense, pharma). Engine tags tickers at audit time. Stops the NVDA + AVGO + AMD + SMCI + MRVL "pretend diversification."

E7 — Weekly Confirmation

Refuses: new entries when weekly EMAs aren't aligned. Half the structural support is missing. Daily trend without weekly = lower-conviction setup.

E8 — Hard-Cash Floor (10%)

Refuses: going below 10% in USFR/SGOV/cash. The sizer refuses to allocate the last 10%. "If you're 100% invested, you can't add."

E9 — Earnings Proximity (≤ 3 sessions)

Refuses: new entries within 3 trading sessions of earnings. Holds and exits unaffected.

E10 — Defensive Oil Cap (15%, war regime)

Refuses: energy > 15% in war regimes (VIX > 25).

E11 — Hardware War Cap (30%)

Refuses: semis + compute infra > 30% in inversion regimes (natgas/oil/uranium term-structure inverted).

E12 — Velocity Exception (35%)

Refuses: sleeve > 35% even on momentum names. Velocity Track tickers can exceed the 25% Sports-Cars cap up to 35%, only while Velocity flag is active AND Armor Cash > 15%.

E13 — Diplomatic Decay (48h post-truce)

Refuses: full-conviction sizing within 48 h of a named truce/summit (Ukraine, Gaza, Taiwan). Sports-Cars score penalized −10. Geopolitics matters to your portfolio whether you like it or not.

The pillars are gates, not rules. They don't generate trades. They filter out trades your technical scanner wants to take but shouldn't.

6. Layer 3 — War mode (VIX > 25)

Activates automatically. What flips:

What you do differently:

Back to baseline triggers when VIX < 25 for 5 consecutive cycles, or when the regime engine clears the WAR label via macro re-classification.

7. Layer 4 — 13-point options (Level 2 only)

Activates when OPTIONS_ENGINE_ENABLED = True in config and the ticker has a Tradier chain available.

The 13 cells (each 0–10):

  1. Structure & Trend — same logic as L1 Point 1 with options-aware loose-trend bucket
  2. Volatility regime — VIX-driven; tighter when VIX > 25
  3. IV Rank — ≥ 30 floor, ≤ 80 cap; deep-ITM filter when in VIX trap
  4. Theta Budget — portfolio theta ≥ MIN_PORTFOLIO_THETA before short premium
  5. Delta Target — −0.30 to 0 for short puts; matches strategy
  6. DTE Preference — 14-day default; 7–60 acceptable
  7. Liquidity — bid-ask < 10%, OI > threshold
  8. Strategy Fit — long call vs vertical spread vs CSP, picked by IV regime
  9. Sentiment Alignment — MarketAux / AI thesis must match strategy direction
  10. Macro Correlation — same VIX/sector/RS structure as L1
  11. Hidden Tape — gamma exposure ratio, dealer GEX, max pain
  12. Manipulation — options-specific sweep + book skew detection
  13. Energy Penalty — applies when oil shock + high-energy ticker

Strategy picker logic:

When to ignore the recommendation:

The options layer is opt-in. If you trade equities only, you can leave it disabled — the dashboard hides the panel. If you trade options, the layer is your structured second opinion. It doesn't pick the trade. It scores it.


Part 3 — The UI, deep

8. Card anatomy — every signal, threshold, edge case

A ticker card has six zones. Top to bottom:

Header

Score row

Whale toolkit (3-col)

Live-data chips (when present)

Execution levels

Position sizer

Pillar chips (bottom row)

Small chips, one per active pillar. Green pass · Red violation · Amber warning. Hover for the specific gate state.

Flags

9. The modal — every tab

Click any card. Modal opens. Header has:

Tabs:

Critical UX rule (v6.7.17): the modal is sacred during a session. Any code path that mounts a coach panel must respect _isModalOpen() or the LLM-loaded coach content gets destroyed. If you're hacking on the dashboard and a coach disappears mid-session, that's the rule you broke.

10. The 10 AI coaches — when, why, what

Coach Trigger Payload it gets What it produces
Pillar Coach Pillar violation/warn Violated pillar + position state + caps "You're at X% in Y; pillar Z says reduce to W"
Exit Coach Score < 70 OR SL approached Position state + new score + signals Sell vs reduce vs wait, with reasoning
Entry Coach ARMED state Full entry context, pillars, R:R, weekly Thesis vs risk in one read
Devil's Advocate Conviction high (≥ 90 + ARMED) Bull thesis + position context Bear case, adversarial — that's the point
Thesis Drift 14d-old AI thesis vs today Both theses + signal diff Where the read changed and why
Position History Audit Held position with score drop Trade history + audit timeline Why this position is no longer scoring
Comparable Setups Today's tape matches prior Comparables + outcome stats What happened last time
Catalyst Interpreter News / earnings / Fed detected Catalyst details + ticker context What it means for this ticker
Whale Confirmation Flow contradicts price Whale data + price action Smart money is in or out
Trap & Structure Trap detector fires Structure state + contradiction details Walks the contradiction in detail

Coach payload contract: each coach receives structured inputs (no free-text). Each produces structured output that the dashboard renders into a fixed panel. No chat box. Ever. The coaches are bound to framework events, summoned by triggers, never by free-form questions.

Threshold-citation guard (v6.6.40+): all coaches inject _THRESHOLD_CITATION_GUARD into their prompts so they cite payload thresholds (entry-score gate, R:R floor, sleeve cap, sector cap, stop %) rather than hardcoding them. This is why a coach saying "the 80/100 entry gate" vs "a 80/100 entry gate" matters: the first is canonical, the second is the AI hallucinating a threshold the framework didn't pass it.

Cache TTL: 5 minutes per coach per ticker. Stale-coach badge fires on the panel when audit data refreshes without a re-classify; user clicks ↻ Regenerate to refresh.

Cost tracking: every coach call logs to ai_thesis_log.jsonl with token counts + model + cost. Cost-meter incident (2026-04-28) caught the bug where the cost calc was missing web_search_requests fees — that's now part of the canonical accounting ($10/1000 web_search calls).


Part 4 — Execution

11. Broker integration — preflight, brackets, ladder

The 8-check preflight chain

Every BUY order runs broker_guard.preflight_new_order() before E*TRADE sees it. Strictly ordered, fail-fast:

# Guard Refuses
0 guard_writes_enabled Master kill switch (set BROKER_WRITES_ENABLED=false to disable all writes)
1 guard_circuit Recent failures > threshold; circuit breaker open
2 guard_rate_limit E*TRADE rate-limit (50/min default)
3 guard_audit_freshness Audit > 15 min old (G6 stale_audit)
4 G1 trade_dollar_cap Notional > MAX_TRADE_USD
— preview returns here —
5 G2 daily_order_budget Rolling 24h order count > MAX_DAILY_ORDERS
6 G4 symbol_cooldown Re-order on same symbol within cooldown
7 G3 new_order_token HMAC token from preceding preview, binds (cid, account, symbol, qty, action, price_type, prices)

G5 — R:R minimum runs inside G1 (v6.5; v6.6.4 limit-price-aware). Refuses BUY when audit R:R < BROKER_RR_MIN (default 2.0). For LIMIT orders, recomputes R:R from planned fill price. Set BROKER_RR_MIN=0 to disable.

Stages: - stage="preview" → skips G2 + G3 (no order placed) - stage="place" → full chain - stage="cancel" → only 0–2 (kill switch never blocks a cancel)

Bracket order flow

Dashboard sends a preview first to get a preview_id. Then place_bracket_order submits the BRACKETED body with two legs:

  1. Entry leg — STOP_LIMIT or LIMIT, GOOD_FOR_DAY
  2. SL leg — STOP or STOP_LIMIT, GOOD_UNTIL_CANCEL (stays after entry fills)

The SL leg auto-opposites the entry action (BUY → SELL, SELL_SHORT → BUY_TO_COVER).

E*TRADE returns order IDs for both legs. Reconciler tracks status.

TP ladder reconciler

broker_tp_ladder.py manages the 40/40/20 scale-out. State file: broker_ladder_state.json. Per ticker:

  1. Snapshot original_qty so 40/40/20 is computed against the starting position even if partials fill.
  2. TP1 placed immediately at the recommended price.
  3. TP2 + TP3 queued internally (NOT placed at broker yet).
  4. Reconcile cycle: query broker for current leg status: - OPEN → keep waiting - FILLED → mark done, advance + place next leg - CANCELLED → user cancelled at broker; mark paused (don't auto-advance)
  5. Source of truth = broker. Local state file is a CACHE reconciled every cycle. Orphan orders we don't recognize are ignored.

Recovery from broker failures

12. Calibration & customization — what to touch, what not to

settings.json (canonical)

Key Default When to change
BROKER_RR_MIN 2.0 Rare. Set 0 to disable G5.
BROKER_MODE live Switch to dryrun for testing without firing real orders.
BROKER_WRITES_ENABLED true Set false for read-only analyst mode.
LICENSE_KEY required Set once, don't touch.
OPTIONS_ENGINE_ENABLED false Enable for L4 options scoring. Requires Tradier chain access.

settings.local.json overrides

Per-user / per-machine tweaks that don't ship to the repo. Same shape as settings.json. Wins over settings.json for any key that's set.

Env vars (for Docker / cloud)

Things you should NOT touch

The framework has been calibrated. If you find yourself wanting to lower the gate to "let more setups through," that's the urge the framework is built to refuse. Tighten your watchlist instead.


Part 5 — Operating reality

13. Edge cases & recovery

Symptom Most likely cause Fix
Audit signal red, > 15 min stale Provider timeout, framework wedged Check topbar; hit refresh; restart daemon if persistent
Topbar broker chip red E*TRADE token expired Settings → re-authorize
All cards grey yfinance rate-limited or down Wait one cycle; check audit_dashboard.log
Coach panel says "loading" forever LLM provider timeout Click ↻ Regenerate; check API key in env
Alerts not firing alerts_engine daemon stopped ps aux | grep alerts; restart
Bracket order rejected (code 100) COID > 20 chars OR genuine service outage Check client_order_id in log; if < 20, retry after backoff
Score moved 5+ points cycle-to-cycle Live data refresh or sentiment swing Look at the cell breakdown; if no clear cause, restart for clean state
TP ladder paused User cancelled at broker Modal → review legs → resume or reset
Modal coach disappeared mid-session Code path didn't respect modal-open guard Bug; reload the page
Version banner says "force upgrade" App version below MIN_VERSION git pull && restart

The "everything turned grey" moment: usually one of three things — provider degradation, license check failing, or the framework process died. Check audit_dashboard.log first. The log will tell you which one.

14. Case studies library

These are the calibration moments that shaped the framework. Each is ~½ page. Read them once; the patterns recur.

VRT TRAP→NEUTRAL (the inverted swept-low rule)

What fired: Original swept-low rule classified VRT as TRAP whenever today swept the prior-day low and close > primary support. VRT had been chronically misclassified TRAP on routine pullbacks.

Root cause: A swept-low that closes above support is a bullish reversal, not a trap. The rule was inverted from the bullish-swept-high TRAP logic without flipping the inequality.

Fix: Geometry classifier now reads swept-low + close > S as NEUTRAL (bullish potential reversal, not failure).

Lesson: When a rule fires on every routine pullback, re-read the rule. It's probably inverted.

Companion case: VRT also produced a published blog post about a separate moment — score 60/D / NO ENTRY — TRAP on VRT despite "trend continuation" being structurally true. R:R was 1.5 (below 2.0 floor); ADX 22; volume 0.52 × normal; RSI 69 daily / 81 weekly; 5 wick sweeps. Framework's read: "Someone is painting this chart sideways-up while distributing — don't be the bagholder who buys $328 on 0.5 × volume after a 30% run." User didn't pull the trigger. Hindsight: would have been right as an investment, not a trade. Trade-quality and structure are separate questions.

AAPL EXTREME→SCHEDULED (10b5-1 distinction)

What fired: insider_transactions._classify_signal() originally flagged any portfolio with ≥ 5 sells, 0 buys, ≥ $5M as EXTREME_SELLING. AAPL fired EXTREME with $25M of sells.

Root cause: ≥ 80% of that volume was 10b5-1 pre-planned — insiders committed months ago while not in possession of MNPI. Today's volume reflects a calendar, not a decision.

Fix (v6.5.0a-4): SCHEDULED_SELLING short-circuit before discretionary classifiers:

if is_predominantly_10b5_1 and sell_count > buy_count:
    return "SCHEDULED_SELLING"

The same false-positive is now an amber/neutral chip when ≥ 80% of dollar volume carries the 10b5-1 flag.

Lesson: Insider data needs context. The number alone is misleading; the type of sale carries the signal.

NVDA TRAP→CHASE (auto-rule override)

What fired: structure_classifier.auto_classify_state() returned TRAP on NVDA from a swept-low pattern.

Root cause: The level wasn't a structural support; price was extended > 1.5 × ATR from S/R; momentum-only setup. That's CHASE, not TRAP.

AI synthesizer override: Flipped the verdict from TRAP to CHASE based on geometry the rules didn't capture.

Lesson: "The auto-rule is the prior, not the verdict — the AI then has a chance to override based on geometry the rules don't capture." Rules give the prior; AI gives the verdict. Both ship to the user's panel with rule reasoning AND AI override note.

PLTR insider sell ($435M Thiel)

What fired: PLTR's insider chip read 🚨 INSIDER SELL ($435M).

Detection: 227 sales vs 0 buys in 6 months. Peter Thiel sold 4M shares in 90 days. Director Moore sold 16k on April 15.

Pattern caught on 3 of 6 calibration tickers: PLTR (Thiel), GOOGL (Pichai 2.53M), NVDA (953,976 shares + 15:0 ratio).

Lesson: Insider-selling detection landed on 3 of 6 calibration tickers — the #1 signal AI consistently catches that the 11-pt framework misses. Drove the v6.5 priority bump making Form 4 ingestion canonical.

MU 2026-05-05 (the trap chip in action)

Setup: - Score: 80/B · HOLD — Bullish · 80 - R:R: 2.45 (clears 2:1 floor) - Entry $640.20 · SL $599.75 (struct, ~6% drawdown) · TP1 $739.42 (3×ATR — no structural cap) - Trap flag: ⚠ Trap: chase-the-top - Weekly: ADX 41.5 (extreme trend) · RSI 80.3 (extreme overbought)

Temptation: every momentum signal is screaming yes. Score is a clean 80. R:R is fine. Daily HH/HL. Bullish news. Call-dominant gamma.

Framework's read: Trap detector caught what the score gate missed. Strong weekly trend on overbought RSI = bagholder pattern. The move has happened. compute_structure couldn't find a primary_R for MU — so the framework can't see where price would actually pause. TP1 sits at $739 because there's no closer ceiling, but that's a 15.5% straight-line run. With weekly RSI at 80, improbable.

Decision: Wait. Watchlist alert at $610–620 — that's where MU pulls back to a tight-structural setup with a real edge.

Lesson: This is the VRT pattern restated. Clean structure, wrong moment. The first override of a ⚠ Trap: flag is the most expensive trade you'll ever make.

The cost-meter incident (meta-case)

What happened: An hour after the v6.4.0 launch, a 12¢ Anthropic charge didn't reconcile with the dashboard's recorded cost.

Two bugs compounding: 1. Whale retry-burn — the Whale Confirmation Coach panel's Retry button fired a fresh paid Anthropic call instead of using the 5-min cache. Stale-cache fallback was missing on the retry path. 2. Missing web_search tool fee — cost calc counted Anthropic input/output/cache tokens but not the $10/1000 server_tool_use.web_search_requests line. Each call invoked web_search 6–8× → recorded cost was ~50% under reality.

Fix: Cost calc reads usage.server_tool_use.web_search_requests from the API response; falls back to scanning content for server_tool_use blocks; adds web_search_requests × $0.01. Whale Retry now uses the 5-min cache; 90s timeout. Per-coach cost capture across all 7 v5.7 AI coaches.

Lesson: "You found a real bug an hour after launch by being annoyed at a 12¢ charge. That's the kind of pressure-testing that catches things." Cost discrepancies are signals.


15. Bug class catalog (the recurring patterns)

These are the bug classes the framework has hit more than once. Each one was caught and shipped a fix; each one tends to recur in new code unless you grep for the pattern.

Pattern Where it shows up Fix
Timezone anchoring time.time() vs getmtime(), daily reset boundaries Use ZoneInfo("America/New_York"); never bare datetime
Atomic writes JSON state files Always temp + os.replace; never write directly
Cross-surface fix-leakage Same scoring logic copy-pasted (11pt vs 13pt) Run diagnostic recipe against BOTH surfaces
Baseline-migration leak Hardcoded constants downstream of new baseline var Grep for the hardcoded value before shipping
Same field, different formula closed filter, win definition, profit factor Rename or unify
Modal-render guard staleness render() blocks during modal-open, data freezes Add targeted in-place rebuild path
DOM-bound observer survival innerHTML rewrite destroys observed subtree Disconnect-and-null at every site that replaces target
Brand-contract sad-path leaks Banners are easy; empty states / toasts / chip tooltips are slow drips Run brand-contract grep end-to-end, not just on banners
DOMContentLoaded race vs render() Component depends on data not yet loaded Cache + v5states:ready re-fire pattern
Hardcoded sticky offsets top: 44px breaks when sticky parents wrap Use var(--Xheight) driven by ResizeObserver
Stacking-context trap Descendant of finite-z-index sticky parent Bump parent's z-index above all floating descendants
Disambiguation tooltips encoding the bug they prevent "NOT to be confused with Pillar N" Scan disambiguation text when fixing labels
Undocumented vendor caps E*TRADE COID 20-char limit Probe boundaries (1, 5, 10, 15, 20, 21, 25)
Symptom-text describing failure category, not cause Generic error text masks specific cause Diff request bytes between working and broken paths
Gate-vs-element-class divergence Class predicate gate (.contains('show')) misses elements Audit every element supposed to flow through the gate

The pattern that's hit most often: same field name carrying different formulas across surfaces. Always rename or unify. Don't trust two surfaces to "do the same thing" because they share a name.


Where to file bugs

If something looks off — a chip that shouldn't be there, a coach that won't load, a score that doesn't match the cell breakdown, a broker order that errors out — write it down before you investigate. A 30-second note ("MU showed Hidden Tape 5 in modal but 6 in compact") becomes an hour-saver six weeks later when you're debugging the same thing.

Three places to write it:

  1. audit_dashboard.log — the framework's own log. Most issues leave a fingerprint here. tail -50 audit_dashboard.log is the first move.
  2. broker_orders.log — broker-specific issues (preflight refusals, place errors, reconciler diffs).
  3. The bug-class catalog above — if it's a pattern that's recurred, add a row.

Swing Deck is a trading framework. Not financial advice.

See Swing Deck Guide Reference for the everyday user manual. See FRAMEWORK_AND_RISK_PILLARS.md for the internal calibration reference (per-cell scoring rubrics, historical case calibration, implementation notes).