fix: audit round 2 — 57 verified defects (entry-protection hole caught live in production) - #103
Merged
Conversation
…weep, prompt fidelity, evolution guardrails Round 2 of the full-codebase audit: verified the 54-finding backlog the round-1 verify fleet never reached (session limit) — 50 confirmed real, 4 refuted — plus 3 fresh finders over the interactions of today's three merged PRs, which confirmed 11 more (7 major). One of the interaction majors was CAUGHT LIVE during this session: the first morning on new code left NEE/CEG naked because their entry limits were still working after the 15s protection wait — exactly the hole fixed here. ENTRY-ORDER LIFECYCLE (interaction majors) - place_entry_protection treated "still working" like "terminal 0-fill" and walked away — a DAY entry could fill hours later with no stop watching. Now: still-working remainders are CANCELLED (protection-first; the post-cancel re-read protects whatever landed). - No exit path cancelled a same-day resting entry BUY: a fully-exited symbol could re-open itself, and emergency liquidation could re-buy into the crash. Full-exit SELLs cancel the symbol's entry orders; emergency liquidation + force_delever cancel ALL entry orders first. - Coverage repair read the last BUY under the executed-only predicate — a same-session 'submitted' BUY was invisible, so the belt no-op'd or applied a months-old stop level. get_symbol_last_buy(include_in_flight=True). - run_intra_check now runs the coverage reconcile+repair every 30-min tick — the naked window for any late fill shrinks from hours to ≤30 min. - get_current_stop_price reported whichever stop Alpaca listed first; multi-stop positions are now the steady state (per-BUY GTC stops). It now reports the HIGHEST (first to trigger) and logs multi-stop cases. - Ex-div adjustment consolidated all stops into one level; now shifts EVERY stop down by the dividend, preserving per-lot geometry (broker.shift_stops_down with cancel/restore rollback). BREAKER × SWEEP (interaction major) - park_excess now refuses to park on a daily-loss-breach day (single choke point): the bookend used to buy ~99% of equity into SGOV right after an emergency liquidation, the next intra tick emergency-sold it with a spurious 🚨, repeating all day. - force_delever unparks only what the deficit needs (not the whole T-bill balance) and records the vehicle's exit as SWEEP_SELL, preserving ledger isolation; recent-sells grading gets the symbol-level belt. RISK / EXECUTION - Non-finite cash failed the cash_only rule OPEN (NaN < 0 is False) — fails closed now, mirroring the NaN market_value guard. - The R/R sanity recheck ran only when the ATR floor widened the stop; the raise-limit-to-market path (which shrinks reward the same way) dodged it. Hoisted: any execution-side geometry change re-checks R/R ≥ 1.2. - ExecutionStage's post-review emergency liquidation priced limits off pre-LLM stale positions — refreshed first. DATA / MEMORY / GRADING - Earnings signal for missed-ops: structured Sentiment line (the naive "bearish" substring dropped NEUTRAL analyses), newest filing per symbol, 90-day recency. - One filing's failure aborted the whole earnings batch (no per-report isolation); prior-analysis pick was lexicographic (every 10-Q outranked every 10-K regardless of date). - Calibration FIFO seeded BUY lots only from the lookback window, so a SELL closing an old lot matched an unrelated newer BUY; lots now seed from full history, the window bounds exits only. - Missed-lessons "recurring" was auto-satisfied by one rolling-window streak; now ≥2 separated episodes OR ≥2 distinct symbols. - Evening BUY grading compared a LIVE stock quote against YESTERDAY's SPY close (same-day buys always showed spy_pct=0); SPY leg is live now. - get_ohlcv routed an all-NaN yfinance frame to [] without trying the Alpaca fallback; _staleness_days counted calendar days (every Monday read "3 days stale"); exDividendDate parsed in host TZ (+1 day drift on the SG host); correlation admitted 10-20-bar symbols as silent all-NaN matrix rows; close session's anti-flip-flop memory excluded the same day's midday row; a macro DB-write failure discarded a successful macro analysis; trail-cooldown wrongly ignored superseded (canceled) trail rows; fund_buys could report freed cash while ctx kept the stale pre-sale value. PROMPT / AGENT FIDELITY (subagent batch) - position_reviewer: entry stop/target lines no longer vanish for positions older than today; macro N/A fallbacks actually engage; grade section renders when only BUY grades exist; one malformed grade no longer destroys the whole EveningReport. - risk_manager: prompt now carries equity/cash/per-position weights (the veto layer's rr_audit ran blind); allocation_pct labelled per action (BUY=% of portfolio, SELL=% of position). - PM sees GROSS weights (was RAW — a "hold SQQQ" read as a 3x add); tech_analyst drops rows for symbols it never submitted; news_analyst renders mention symbols, gains a close-session mode, and word-boundary matches state-change symbols; meta_reflector renders watchlist_candidates. - position_reviewer prompt no longer claims "TRAIL_STOP is always permitted" (the executor clamps it) or a universal SELL hard-trigger gate (it applies to already-trimmed symbols only). - PM parse failure returns analysis_error (retryable, loud) instead of masquerading as a deliberate "no_trades" hold. EVOLUTION / OPS (subagent batch) - quarterly snapshot's budget `break` starved the Learnings section for every agent (break→continue; the hiding test now exercises the branch). - apply-from-saved-reflection lane (EVOLUTION_APPLY_SAVED): what the human reviewed is exactly what gets applied — the documented gate re-ran the LLM. - learning_text newlines defeated the line-based guardrails (normalized); empty apply runs leave an audit-log marker; auto-commit refuses to sweep operator-dirty prompt files. - Evening/meta Telegram meta lines read the real ApplicationReport shape (were dead code); scheduler CronTriggers pinned to ET; healthcheck success pings skip intra_check (14/day pings kept the dead-man green while morning died); TELEGRAM_DISABLED accepts 1/true/yes/on in the wrapper. Tests: 1430 green (+~110 new regression tests across 3 new test files). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PQkESoSTYx2bCy7WYnTPXR
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Audit round 2: 57 verified defects, including a hole caught live in production
Method
Round 1's verify fleet was cut off by the session limit with 54 findings never verified. This round: (1) verified that full backlog — 50 confirmed, 4 refuted; (2) ran 3 fresh finders over the interactions of the three PRs merged earlier today (#100/#101/#102), confirming 11 more (7 major). Every fix traces to an adversarially-verified finding with reproduction evidence.
Caught live while fixing
The first production morning on the new code (09:30 ET today) demonstrated interaction-major #1 in real time: EQNR filled within the 15s protection wait and got its GTC stop; NEE/CEG were still
status=new, the old code logged "filled 0 — nothing to protect" and walked away, and both filled minutes later — naked. (Paper account; production's midday coverage-repair re-protects them.) That exact hole is fixed here: still-working entries are cancelled after the wait, the post-cancel re-read protects whatever landed, andrun_intra_checknow runs the coverage reconcile+repair every 30 minutes, shrinking any residual naked window from hours to ≤30 min.Highlights by area
Entry-order lifecycle — still-working entries cancelled (protection-first); full-exit SELLs cancel the symbol's same-day entry BUYs; emergency liquidation and force_delever cancel ALL entry orders (a resting DAY buy re-bought into the crash being liquidated); coverage repair reads in-flight BUY rows;
get_current_stop_pricereports the highest of multiple stops; ex-div shifts EVERY stop preserving per-lot levels.Breaker × sweep —
park_excessrefuses to park on a breach day (the bookend used to buy ~99% of equity into SGOV right after an emergency liquidation, and the next intra tick emergency-sold it — a deterministic all-day wash loop with spurious 🚨 pushes); force_delever unparks only what the deficit needs and records it as SWEEP_SELL (ledger isolation).Risk/execution — non-finite cash failed
cash_onlyOPEN (fails closed now); the executed-geometry R/R recheck also covers the raise-limit-to-market path; post-review emergency liquidation prices off fresh positions.Data/memory/grading — earnings signal uses the structured Sentiment line + newest-filing-per-symbol + 90d recency; per-report isolation in the earnings batch; date-keyed prior-analysis pick; calibration FIFO seeds lots from full history (window bounds exits only); "recurring miss" = ≥2 separated episodes or ≥2 symbols; live-SPY leg in BUY grading; all-NaN yfinance frames route to the Alpaca fallback; business-day staleness; UTC ex-div parse; close session sees midday's own decisions.
Prompt/agent fidelity — RM finally sees equity/cash/weights (its rr_audit ran blind); allocation_pct labelled per action; reviewer entry-context no longer vanishes for positions older than today; PM sees GROSS weights; tech_analyst rejects unsolicited symbols; news close-session mode + word-boundary symbol matching; one malformed grade no longer destroys the EveningReport; PM parse failure = loud retryable
analysis_error, not a fake "no_trades" hold.Evolution/ops — quarterly snapshot's
breakstarved Learnings for every agent; apply-from-saved-reflection lane (EVOLUTION_APPLY_SAVED) makes the human-review gate real; newline-proof guardrails; auto-commit refuses operator-dirty prompt files; the evening/meta Telegram meta lines read the real report shape (were dead code); healthcheck success pings skip intra_check (14/day pings kept the dead-man green while morning died); TELEGRAM_DISABLED accepts 1/true/yes/on.Refuted (4)
FIFO partial-exit triple-count, sector-guidance sanitizer drop, evening grade isolation claim (misread comment), prohibited-word tripwire scenario — details in the verify transcripts.
Test plan
test_audit_round2.py,test_agents_audit_round2.py,test_ops_audit_round2.py)🤖 Generated with Claude Code
https://claude.ai/code/session_01PQkESoSTYx2bCy7WYnTPXR