- Root cause of the
/ads.txtredirect confirmed and removed. With Page Rule API access the zone showed exactly one active Page Rule:qrak.org/ads.txt→ 301https://semanticsignal.qrak.org/ads.txt. Page Rule patterns match the URL including its query string, which is why the query-less URL redirected while?anythingreached Pages. The rule was deleted and the URL Rewrite workaround from the entry below was removed with it —/ads.txtnow serves the file straight from Pages (200 text/plain, AdSense recordpub-0077039593558808, verified with a Googlebot user agent too). One disabled legacy Page Rule remains (qrak.org/*→.../landing, statusdisabled); it has no effect and was left alone. - Note for future sessions: the account-owned
CLOUDFLARE_API_TOKENcannot touch Page Rules (error 1011), and a user token with the right permissions still answers9109/empty zone lists until a zone is assigned under Zone Resources. Page Rules were reached with the Global API Key sent asX-Auth-Key+X-Auth-Email; tooling lives in thecloudflare-pages-deployskill (scripts/cf-page-rules.py, now tries each credential until one can see the zone).
- The repository's default branch is
master, so Dependabot alert 78 (devalue5.8.1 → 5.9.2, already fixed ondevelopand pushed) stays open untildevelopis merged intomaster.
website/public/llms.txt— llmstxt.org-style index of the site for LLM tools: verified facts (tests, indicators, retrieval sizes, modes), page list, repositories, and an explicit note telling model authors not to summarise this as a profitable or production system.website/public/project.json+project.schema.json— the same facts as structured JSON, with astatusblock (paper capital, testnet executor, unproven profitability, reconciliation as the known weak spot) and anot_claimslist so downstream summaries carry the caveats.website/scripts/build-llms-full.mjs— generatesdist/llms-full.txt(every page as one plain-text document, currently 10 pages / 37 KB) from the built HTML, wired intonpm run build(build:siteruns Astro alone). Generated, never hand-edited, so it cannot drift from the deployed pages.robots.txt: explicitAllow: /for the AI/assistant crawlers (GPTBot, OAI-SearchBot, ChatGPT-User, ClaudeBot, Claude-User, Claude-SearchBot, anthropic-ai, PerplexityBot, Perplexity-User, Google-Extended, Applebot-Extended, CCBot, meta-externalagent, Amazonbot, DuckAssistBot, cohere-ai, YouBot, Bytespider, PetalBot) plus a Cloudflare Content-Signal line (search=yes, ai-input=yes, ai-train=yes).Layout.astro: JSON-LD extended to a@graphwithWebSite+SoftwareSourceCode(code repository, runtime, licence, keywords),rel="alternate"links to/llms.txtand/project.json, and a footer line listing the machine-readable files.
/ads.txtreturned a 301 tosemanticsignal.qrak.orgwhile the same path with any query string served the file — a legacy Page Rule whose pattern has no query string, so it only matched the query-less URL. Account-scoped API tokens cannot read or edit Page Rules (error 1011), and the zone has no other redirect source (thesemanticdynamic-redirect rule is disabled, no Bulk Redirects, no Worker routes). Fixed with a zone URL Rewrite Rule (http_request_transform, description says it is a workaround): a URL Rewrite takes precedence over Page Rules, so/ads.txtwith an empty query is rewritten to/ads.txt?static-file=1and Pages serves the real file —https://qrak.org/ads.txtis now200 text/plainwith the correctpub-0077039593558808record. Delete the Page Rule in Rules → Page Rules and this rule can go; it exists only to route around it.
- The repository's default branch is
master, so Dependabot alert 78 (devalue5.8.1 → 5.9.2, already fixed ondevelopand pushed) stays open untildevelopis merged intomaster.
- Landing page (
website/src/pages/index.astro) rewritten. The scoreboard now includes the rows where this project loses — no real-money trading, no production history, not hosted for you — plus?wherever a competitor's documentation could not be verified, instead of a wall of ✘. A new "where every number comes from" section lists the repo paths behind each claim. /storyrebuilt fromgit log. Timeline dates are now the real ones:chart_generator.py2025-12-22 (git log --diff-filter=A),brain_experience/brain_context/brain_reflection2026-05-16,.ai/2026-07-26, executor integration 2026-08-14, provider consolidation 2026-09-12. Added an "Honest status" section (paper capital, testnet executor last exercised 2026-08-15, profitability unproven) and an errata section listing the claims this site previously got wrong.- Claims removed: "Kelly Criterion position sizing" (no Kelly code exists in
src/; sizing is the model's proposal capped at 10% of capital with 1/2/3% fallbacks), "hard 1.5 R/R floor rejects the signal" (min_rr_entry = 0.0; EV is the only hard gate), "how the system earns real money" (executor runs withENABLE_TESTNET=true), "zero lint errors" (ruff check .reports 22 findings), and the "1,270+ / 1,380+ automated tests" numbers. - Test count is now generated from a run, not typed:
1,549collected /1,532passed /17skipped —python -m pytest tests -qon the Windows venv, 55s. - Articles: the
_ema_numbasample was replaced with the realsupertrend_numbafromsrc/indicators/trend/trend_indicators.py; retrieval described as it works (k=3experiences, 20-trade stats, 5 blocked-trade snippets, 3 rules); the executor article rewritten around the sevenSafetyGuardchecks and the verdict journal, with the reconciliation caveat stated instead of a dead-letter queue that does not exist. - Privacy policy states that no ad script is loaded today; disclaimer now says testnet and names the changelog-documented losing-streak reset.
website/src/pages/404.astro— until now Cloudflare Pages answered every unknown URL with200and a copy of the homepage.website/public/{favicon.svg,og-image.png,ads.txt}— browsers were being served the HTML shell in place of a favicon, there was no social card, and noads.txtfor AdSense (pub-0077039593558808).- Canonical URLs,
og:image/ Twitter card,theme-color,rel="noopener"on external links, and a footer line naming the stack with a link to this site's own source.
website/astro.config.mjshadsite: 'https://semanticsignal.qrak.org'(the dashboard host) — canonical URLs for aqrak.orgdeployment pointed at the wrong origin.website/public/sitemap.xml: trailing slashes (what Pages actually serves) and refreshedlastmod.
devalue5.8.1 → 5.9.2 (website/package.json+ lockfile) clearing GHSA-9rgm-9g3h-6x36 (moderate DoS via malformed input);npm audit→ 0 vulnerabilities,npm run build→ 11 pages.- Note:
/ads.txtstill returned a cached301tosemanticsignal.qrak.orgon the bare URL after deploy while the same path with any query string served the file correctly — consistent with a legacy Page Rule / cached redirect that the account-scoped API token cannot inspect (Page Rules endpoint does not support account owned tokens, error 1011). Left for the user to check in the dashboard.
- One shared floor policy.
src/trading/rr_policy.py(new) owns the entry floor:max(config.MIN_RR_ENTRY, brain rr_borderline_min), plus normalization (0preserved, non-finite/negative values fall back safely). The prompt renderer and the executor both callresolve_entry_rr_floor(), so the model can no longer be shown a floor the executor does not enforce. Before this,Config.MIN_RR_ENTRYdefaulted to1.0and an untrained brain always reportedrr_borderline_min = 0.5, so a configured0never actually disabled the gate. min_rr_entrydefaults to0.0(config/config.ini.example,Config.MIN_RR_ENTRY,BrainContextProvider). With no learned floor the gate is inactive and R/R stays an EV input instead of a veto. The prompt now renders "No hard R/R floor is active" rather than the meaninglessR/R < 0.0: REJECTEDhard block.- The brain can only add
0.5or1.0, and only from evidence. It needs at least 10 closed trades below 1.0 R/R (with at least one loss) before it looks at that bucket's expectancy: below −0.05R raises the floor to1.0, between −0.05R and0raises it to0.5, positive expectancy leaves it at0.0. The old ladder that jumped straight to1.3/1.5/1.8after 3 sub-threshold trades is gone, along with the choppiness hack that silently lowered the floor. - Prompt honesty pass (
template_manager.py,ev_formatter.py): the prompt no longer calls R/R the only hard gate, documents the executor's SL/TP normalization (SL expanded to ≥1%, clamped to ≤10%, TP clamped to ≤50%, R/R recomputed from the corrected levels), labels the historical winning-average R/R and SL figures as guidance rather than caps, and points the PRE-FLIGHT CHECKLIST at Decision Rules instead of a stale section. The ADX trend threshold is read from the brain instead of a hardcoded 25.
- R/R floor assertions updated in
tests/domain_brain/test_vector_memory.py,test_brain_learning.py,test_prompt_template.pyandtests/domain_trading/test_risk_management.py, plus new coverage that a profitable low-R/R bucket keeps the floor at0.0and that the prompt drops the hard block when no floor is active. - Full suite green (
499 passedin the R/R-affected modules;ruff check src start.pyclean;pyright src start.py0 errors / 0 warnings).
src/platforms/ai_providers/base.pyandgoogle.py: anoverloaded/503 UNAVAILABLEresponse is now logged at warning. The condition is already handled downstream —ProviderOrchestratorretries on the paid key (logged as a warning) and reports a genuine failure at error level when the paid client also fails — so the provider-sideerrorlevel only added two benign lines toerrors.logon every cycle and buried real failures.rate_limit/quota,authentication,timeout,connectionand unexpected errors stay at error. A healthyerrors.logis now empty on a normal day; the overload still shows inBot.logat warning level.
- Every module and class is now under 1000 lines. Before:
start.py1397,src/dashboard/routers/brain.py1238,src/trading/trading_strategy.py1209 (classTradingStrategy1156). All splits are behaviour-preserving moves into mixins the existing classes inherit, so every call site and test seam keeps working:src/composition/provisioners.py(new,ProvisioningMixin): the 9 provisioning stages plus the directory/maintenance/startup-summary helpers;start.py1397 → 502.src/composition/startup_support.py(new): env + GPU probe, optional Tk error dialog, console banner, startup summary table.src/trading/executor_reconciliation.py(new,ExecutorReconciliationMixin): executor position verification, verdict-journal correlation, phantom rollback.src/trading/position_management.py(new,PositionManagementMixin): entry, SL/TP updates, existing-position decisions.trading_strategy.py1209 → 480.src/dashboard/decision_presenter.py(new): the pure view-model builders (decision graph + synopsis, market status, current market context) moved out ofrouters/brain.py(1238 → 702).
_open_new_position(235 lines) decomposed into_reject_intent,_store_risk_frictions,_check_entry_thresholdsplus the entry body; the three exit-check entry points now share_close_on_exit.
- Admin config path after the composition split:
_provision_dashboard_layerderivedconfig/config.inifromPath(__file__).parent, which resolved tosrc/composition/once the method moved. Now anchored on aPROJECT_ROOTconstant.
- All prose
#comments (1 980 full-line + 339 trailing), keeping only machine directives (# noqa,# type: ignore,# pylint:,# pragma:) — one# noqa: SIM103that shared a line with prose was preserved. - Docstring
Args:/Raises:boilerplate that restated signatures, across 75 files (2 136 lines);Returns:sections and dict-key documentation kept.
tests/test_trading_strategy_branches.py: the 27ENTRY_CONFIRM_*patch targets repointed tosrc.trading.executor_reconciliation— patching the old module would have patched a dead name and silently stopped intercepting.- Two test files import the relocated dashboard helpers from
src.dashboard.decision_presenter. - Full suite green;
ruff check src start.pyclean;pyright src start.py0 errors / 0 warnings.
- In-place reload (SHIFT+R): in the bot console, SHIFT+R now performs a full graceful shutdown and exits with code
42; the launcher scripts (re)start the bot in the same window, so source/config edits apply with no manual restart. The shutdown runs to completion (all callbacks, awaited like the Ctrl+C path) before the exit code is returned (start.pyRELOAD_EXIT_CODE). Guard: the command refuses politely unless the launcher exportsLLM_TRADER_RELOAD_SUPPORTED=1. - Launcher relaunch loops:
scripts/start_script_main.ps1,start_script_develop.ps1,start_script_futures.ps1,start_script_main_linux.sh,start_script_main_macos.shrestart the bot on exit code 42 (plus a banner hint). tests/test_reload_command.py: reload flag semantics, command guards (env + already-shutting-down), SHIFT+R key matching.
- Linux/macOS launchers: empty-array expansion under
set -u(stock macOS bash 3.2 would abort on a default no-argument start); the requirements-check failure path no longer prints the__CHECK_FAILED__sentinel as a package name (honest message + exit code, pip install extracted into one function);-twith no value now reports cleanly.
- EV fee basis (
src/analyzer/formatters/ev_formatter.py): the round-trip fee was computed from the whole portfolio (0.075% of $10k = $7.50 per trade) although positions are capped at 8% ($800) — ~6× the real ~$1.20 round trip. The inflated fee alone flipped gross-positive candidates negative (e.g. gross +$2.02 → EV −$5.48) and the $11.25 entry threshold inherited the same basis, silently suppressing entries in the flat market. The fee now scales with the position notional (0.150% round trip) and the worked example/threshold anchor on the standard NEUTRAL 8% cap — $1.20 fee → $1.80 threshold at $10k — pinned by test toRegimeRiskProfileSelector.get_position_size_cap(NEUTRAL).
- Dead
EVFrameworkFormatter.build_ev_quick_section(no production caller, never present in any prompt dump) and its test.
tests/test_ev_formatter.py: round-trip fee scales with notional; position-based worked example; regression guard keeping the old capital-based $7.50 fee out.
- npm tree in
website/refreshed to clear all 9 open Dependabot alerts: astro 7.1.3 → 7.3.2 (CRITICAL GHSA-26w7-cxv4-gfx2 + MEDIUM GHSA-376h-93r7-7g6f), plus overrides for transitive deps — sharp ^0.35.4, svgo ^4.1.0, browserslist ^4.28.7, js-yaml 4.3.2, smol-toml ^1.7.1, baseline-browser-mapping ^2.11.0.npm auditafter refresh: 0 vulnerabilities;npm run buildOK (10 pages).
- Ticker validation vs lazy exchanges: the strict validator ran at startup before any exchange was loaded (
ExchangeManagerloads venues lazily), so it always saw zero symbols — "Exchange symbol data unavailable" on every start and no ticker was ever validated.TickerManagernow callsExchangeManager.ensure_symbols_loaded()(loads the first reachable supported exchange — ~1.4s on binance, cached and reused by the trading path) before validating; the warning remains only for a genuinely unreachable venue. - Startup log / summary provider name:
start.pyread a non-existentAI_PROVIDERkey, so the fallback-chain log line and the summary table printed "googleai" regardless ofproviderin config.ini — now readsconfig.PROVIDER. - Launcher dependency check: the pre-launch check in
scripts/start_script_*.ps1/.shonly verified that a package name was installed, so version floors (>=, ranges) above the installed version were treated as satisfied and pip never ran. It now evaluates real version specifiers viascripts/check_requirements.py(packaging) and runspip install -r requirements.txtonly when a constraint is actually unmet;packaging>=24.0declared in requirements.txt.
- OpenRouter on the raw
openaiSDK:OpenRouterClientnow usesAsyncOpenAI(base_url = https://openrouter.ai/api/v1);reasoningeffort travels viaextra_body; generation cost/stats come from the REST endpointGET /api/v1/generation?id=…(httpx) with the same mapping (total_cost,native_prompt_tokens,native_completion_tokens, …), same signature/retry_delaysemantics; the SDKserver_urlfallback and__aexit__/__exit__cleanup hacks are gone. Wire parity verified live (captured request kwargs, old vs new, for text + chart calls). - LM Studio on the raw
openaiSDK:AsyncOpenAIagainst the server's OpenAI-compatible/v1endpoint; model auto-select viaGET /v1/models(cached); streaming keeps the per-chunkcallbackand partial-output semantics and now records tokenusagewhen the server provides it; the "System: …" user-prefix rewrite and the GPU-crash error mapping are unchanged. Verified with unit mocks + a stub OpenAI-compatible HTTP server. - Startup banner (
start.py): redrawn, complete "LLM TRADER" wordmark (unicode block art) with a "v1.1" version stamp; provisioning steps unchanged (Stage 1/9 … 9/9).
- Dependencies:
openrouter>=1.1.10andlmstudio==1.5.0removed fromrequirements.txt— DeepSeek, OpenRouter and LM Studio now share theopenaitransport.
- OpenRouter reasoning effort: now sent on every request. Previously the first call consumed
openrouter_reasoning_effortfrom the shared model config (in-placepop), so all later calls silently dropped it — found during the live transport-parity capture and fixed by popping from a per-call copy (regression test added).
- DeepSeek provider (
src/platforms/ai_providers/deepseek.py):DeepSeekClientspeaking the official OpenAI-compatibleapi.deepseek.comAPI via theopenaiSDK — text + vision (chart) support.deepseek-flash(DeepSeek-V4.1-Flash) handles images natively (verified live) — one model for text + charts, no vision-model split. - Config:
[ai_providers]→deepseek_base_url,deepseek_model(+ optionaldeepseek_vision_modeloverride);[model_config]→deepseek_reasoning_effort(low|high|max),deepseek_max_tokens;DEEPSEEK_API_KEYinkeys.env;provider = deepseekis now a valid selection. - Cost tracking:
deepseekbucket indata/trading/api_costs.json, dashboard/api/monitor/costs, and peak/off-peak reference rates inconfig/model_pricing.json. - Tests (
tests/test_deepseek_provider.py): SDK wiring, reasoning-effort forwarding, multimodal shape, orchestrator text/vision routing, fallback-chain membership.
deepseekjoins theallprovider fallback chains (text + chart).BaseAIClient._extract_user_text_from_messagesshared by the OpenRouter and DeepSeek clients (DRY).- Dependencies:
openai>=2.49.0promoted to a direct dependency inrequirements.txt(DeepSeek client transport; previously only transitive via crawl4ai/litellm). - Model defaults refreshed (2026-09): OpenRouter fallback →
deepseek/deepseek-v4.1-flash(the previousdeepseek/deepseek-r1:freeno longer exists on OpenRouter — verified against the live model list); loader defaults aligned with the live config (google_studio_model→gemini-3.8-flash, OpenRouter base →google/gemini-3-flash-preview). - ai_providers cleanup:
_prepare_multimodal_messagesdeduplicated intoBaseAIClient(OpenRouter/BlockRun copies removed); deadunwrap_responseparameter dropped fromconvert_pydantic_response; Sep-2026 model docstrings/defaults refreshed;requirements.txtfloors raised (google-genai>=2.14.0). - Copy refresh: dashboard landing + public site now say "multimodal AI" (no vendor branding); test-count claims updated to "1,380+"; "7-month" journey claims refreshed to "9-month"; quick-start key hints no longer claim a dead Google free tier.
- DeepSeek model id: switched to the canonical
deepseek-flash(DeepSeek-V4.1-Flash, released 2026-09-10, native multimodal). The legacydeepseek-v4-flashstring still resolves but self-reports asdeepseek-flash;deepseek-v4.1-flashis rejected by the API. Updatedconfig.ini,config.ini.example, loader default,model_pricing.json, test stubs, and the CI workflow. - Single-model DeepSeek: removed the
deepseek_vision_modeloverride and theProviderMetadata.chart_modelmechanism — the DeepSeek provider always usesdeepseek_model(the app requires vision-capable models end-to-end).
- Project Showcase Website (
website/): Built Astro static site showcase with interactive landing and project story pages (src/pages/index.astro,src/pages/story.astro,src/layouts/Layout.astro). - Codacy Security Scan CI Workflow (
.github/workflows/codacy.yml): Configured automated security scanning and SARIF report upload usingupload-sarif@v4. - SARIF Remediation Engine & Test Suite (
scripts/fix_sarif.py,tests/test_fix_sarif.py): Resolved GitHub Code Scanning upload failures by fixing nulltool.driver.rulesarrays and normalizing non-standard result level enums to SARIF standard enums ("none","note","warning","error"). - Architecture & Journey Article (
articles/architecture_and_journey.md): Detailed technical journey and architectural overview.
- Regime Risk Profile Refactor: Replaced
risk_profile_selector.pywithregime_risk_profile.pyfor regime-aware profile selection integrated intoRiskManager,BrainContext, andMarketConditions. - WebSocket DI Compliance: Enforced dependency injection for
ConnectionManagerinstantiated at composition root instart.pyand passed down toDashboardServer. - Dependencies: Updated
beautifulsoup4(>=4.15.0) andcrawl4ai(>=0.9.2) inrequirements.txt.
- ATR 0.0% Wiring Bug: Fixed zero-value ATR calculation in
brain.pyandanalysis_engine.py. - Dead Code & Lint Cleanup: Removed 25 confirmed-dead items across core modules and resolved all ruff linting errors.
- Nitter Sentiment Analyst: Removed deprecated and unreliable
NitterSentimentAnalystmodule and associated tests (test_nitter_sentiment.py). - Cleaned up Nitter references across initialization (
start.py,app.py), configuration loader, and vector memory context.
- 768D Vector Memory Model Upgrade: Switched ChromaDB vector embedding engine to
BAAI/bge-base-en-v1.5(768-dimensional embeddings). Legacy 384D ChromaDB collections require re-indexing/re-creation on upgrade.
- Expected Value (EV) Framework (
src/analyzer/formatters/ev_formatter.py) — calculates win rates, Expected Value ratios, and R:R thresholds for prompt context synthesis - Social Sentiment Analysis Modules:
src/analyzer/nitter_sentiment.py— decentralized Twitter/X sentiment scraper and processorsrc/analyzer/sentiment_analyst.py— multi-source social sentiment scoring engine (Reddit & Nitter)
- Risk Profile Selector & RL Policy:
src/trading/risk_profile_selector.py— dynamic regime-aware risk profile selectionsrc/trading/rl_policy.py— reinforcement learning post-mortem feedback loop for position size adjustment
- Public Showcase Landing Page (
src/dashboard/static/landing.html,layout.css) — interactive landing page for Semantic Signal LLM Trader dashboard
rag_engine.py— updated RAG engine initialization logic to integrate social sentiment streamstemplate_manager.py&prompt_builder.py— injected EV metrics and social sentiment indicators into primary analysis prompts
- Live Console tab on public dashboard — real-time log streaming via WebSocket, styled like
richterminal output with level-based color coding (ERROR=red, WARNING=yellow, INFO=gray, DEBUG=dim) - ConsoleBuffer (
src/dashboard/console_buffer.py) — in-memory day-grouped ring buffer, max 7 days, clears on restart - ConsoleRouter (
src/dashboard/routers/console.py) — public REST endpoints (/api/console/recent,/api/console/pages,/api/console/page/{n}) + WebSocket (/api/console/live) for live streaming - Day page navigation — buttons for each historical day, auto-fetched from buffer
- Level filter (All/Errors/Warnings/Info+), auto-scroll toggle, clear button
DashboardServer— wires ConsoleBuffer, ConsoleRouter, and lifespan consumer taskmain.js— imports and initializes ConsolePanel module
- Pillow 12.2.0 → 12.3.0 — 12 CVEs: heap OOB write (CVE-2026-59199, CVE-2026-59205, CVE-2026-59197), decompression bomb (CVE-2026-59200, CVE-2026-54058/59/60, CVE-2026-55379/80), TGA heap leak (CVE-2026-59198), JPEG2000 DoS (CVE-2026-59204), EPS infinite loop (CVE-2026-59203), Windows command injection (CVE-2026-55798)
- astro ^6.4.6 → ^7.1.0 — 3 CVEs: XSS via unescaped spread attribute names (CVE-2026-59729), XSS via transition:* directives (CVE-2026-59727), reflected XSS via View Transition properties
- js-yaml → 4.3.0 override — YAML merge-key chains force quadratic CPU (CVE-2026-59869)
- sharp → 0.35.3 (transitive) — libvips CVEs (CVE-2026-33327/28, CVE-2026-35590)
- svgo → 4.0.2 (transitive) — removeScripts plugin bypass
- openrouter 0.9.1 → >=0.11.0 — SDK compatibility (presence_penalty removed)
- Futures LONG/SHORT signals:
template_manager.pyemits LONG/SHORT in prompts whenmarket_type=futures;position_extractor.pyregex + valid_signals accept LONG/SHORT;executor_handler.pyACTIONABLE_SIGNALS includes LONG/SHORT (signals now unified: BUY=LONG, SELL=SHORT) - MARKET_TYPE config:
config.ini.example+Configproperties (MARKET_TYPE,ENTRY_ORDER_TYPE) — spot vs futures, market vs limit - OpenRouter reasoning effort:
config.ini.exampledocumentsopenrouter_reasoning_effort(none→max);openrouter.pypops it from model_config and passes asreasoning={"effort": ...}extra kwarg - Executor dead-letter queue:
data/trading/failed_forwards.jsonl— when executor forward fails after all retries, payload is persisted for replay instead of being silently lost - Retry on executor forward:
executor_handler._forward()decorated with@retry_async(3, backoff×2, max 30s) - Google image token estimation:
google.py—_get_image_dimensions()parses PNG/JPEG headers without full decode;_estimate_image_tokens()calculates Gemini tile-based token cost (258 tokens per 75×75 tile)
- Executor forward prioritized:
app.pysends to executor BEFORE Discord notification + file persist — trade execution is the priority - Executor payload hardened:
_build()refuses to build whenstrategy_decision is None(analysis never validated), usesstrategy_decisionfields (quantity, price, stop_loss, take_profit, confidence, reasoning) instead of raw analysis dict - order_type from config: executor payload uses
self._config.ENTRY_ORDER_TYPEinstead ofanalysis.get("order_type")— no more LLM-controlled order type - Timestamp precision: executor payload timestamp format changed to
%Y-%m-%dT%H:%M:%S.%f(microseconds) - Chart resolution reduced: 4K (3840×2160) → 1080p (1920×1080) — cuts Google image token cost by ~75%
- CLOSE guard:
trading_strategy.py— queries executor API before sending CLOSE; if no position tracked on exchange, skips with warning (prevents double-close or close on unfilled limit order) - UPDATE guard: verifies executor has position before sending SL/TP update; fails closed on network error
- SL widening cap: rejects stop-loss widening beyond 150% of original SL distance from entry — AI can only tighten or keep stops, not blow out risk
- Ambiguous position_size rejected:
position_extractor.py— numbers > 1.0 without%suffix now trigger warning + None (was blindly dividing by 100, risking 50→0.5 misinterpretation)
- OpenRouter presence_penalty: filtered out from
_known_unsupported_params(removed in SDK 0.11+) - Test assertion:
test_openrouter_provider.pyupdated to expectpresence_penaltyabsent from sent kwargs
scripts/start_script_develop.ps1— dead develop-mode startup script
- DRY:
_execute_market_knowledge_update— extractedanalysis_typevariable instead of if/else branches with identical log format strings. - DRY: Market knowledge fallback message — extracted duplicated
"continuing with cached/partial market knowledge"string into_MARKET_KNOWLEDGE_FALLBACK_MSGmodule constant, used in both TimeoutError and Exception handlers. - DRY:
_wait_for_next_timeframe/_wait_until_next_timeframe_after— extracted shared timeframe arithmetic into_calculate_next_check(source_time_ms)helper. Both methods now call the helper and handle only their unique logging + edge cases. - SRP:
MarketConditionsExtractor— extracted 4 methods fromTradingStrategy(was 1151 lines / 19 methods → now 945 lines / 15 methods):extract_price(result)←_extract_price_from_resultextract_market_conditions(result)←_extract_market_conditionsextract_confluence_factors(result)←_extract_confluence_factorsbuild_conditions_from_position(position)←_build_conditions_from_position(static)- New class wired through composition root in
start.py, injected intoTradingStrategy.__init__viaconditions_extractor=.
- Unused imports cleaned — removed
re,classify_bb_position,classify_macd_signal,classify_market_sentiment,classify_order_book_bias,classify_rsi_label,classify_volume_state,classify_volatility_levelfromtrading_strategy.py(only used by extracted methods).
src/trading/market_conditions_extractor.py— new class with constructor DI (logger), 3 instance methods + 1 static method.tests/test_app_timeframe_wait.py— 9 tests covering_calculate_next_check,_wait_for_next_timeframe, and_wait_until_next_timeframe_after.
- Prompt now includes time since last closed position and its direction (LONG/SHORT) when no position is open —
TradingStrategy._get_last_closed_position_info()queries SQLite trade history via existingpersistence.sqlite_history.query().
get_position_context(): extracted shared## Capital Statusheader intocapital_headervariable — DRY, no duplicate string literals.
- 23 defensive checks purged total —
getattr/isinstance/hasattron guaranteed types:post_mortem.py: 14getattr(closed_position, ...)→ direct attribute access (Position/TradeDecision are dataclasses)pattern_quality_scorer.py: 4isinstance(pattern_list, list|str)→ patterns dict shape is fixed by our own PatternAnalyzervector_memory.py: 1isinstance(serialized, dict)→serialize_for_jsonalways returns dict for dict inputbrain.pyrouter: 2getattr(self.vector_memory, ...)→ injected service always has those attrstemplate_manager.py: 3isinstance(data, dict)+getattr(self.config, ...)→ JSON parse + config attrs are guaranteedapp.py: 3 —isinstance(analysis, dict)on typed param (only caller already checks),getattr(self.config, "EXECUTOR_API_ENABLED")+getattr(self.config, "EXECUTOR_API_URL")on Config dataclasspipeline.py: 1 —hasattr(guard, "invalidate_cache")on already name-identified CooldownWindowGuard
test_admin_edge_cases.py: 5TestWritableConfigEdgeCasestests →async def+awaitinstead ofasyncio.get_event_loop().run_until_complete()(dashboard tests killed the loop during teardown)test_admin_live.py:browserfixture → gracefulpytest.skip()when Playwright chromium binary unavailable (Ubuntu 26.04 unsupported)huggingface-hubupgraded 1.2.3 → 1.23.0 (transformers demanded>=1.5.0, blockedtest_blocked_trades_integration.py+test_edge_cases_feedback.py)log_stream.py: removed unusedimport timeandfrom typing import Anyadmin.py: removed unusedverify_admin_sessionimportcrawl4ai_enricher.py:# noqa: F401→# pylint: disable=unused-import(pylint ignores flake8 pragmas)brain.py: movedMarketConditionsunderif TYPE_CHECKING(only used in quoted annotations)pattern_quality_scorer.py:category→_category(unused loop variable)
_extract_usage_metadatacapturesthoughts_token_countand sums it intocompletion_tokens— Google bills thinking tokens as output ("Output price including thinking tokens"). Previously onlycandidates_token_countwas counted, causing ~3.5x cost underreporting vs actual Google Cloud charges.
- Decision Pathways panel: zoom controls (+/−/fit), label truncation with hover title, horizontal node spreading, keyboard zoom, deferred vis-network init, tab-switch delay 300ms.
- Cache-bust version bumps: style.css?v=7.2, main.js?v=7.3, modules/*.js bumped.
- config.ini.example: timeframe warning note.
- Relaxed test assertion from hardcoded version to
?v=pattern.
- Defensive
try/exceptguard aroundthoughts_token_count— the outerexcept AttributeErrorcatches missing fields. No backward-compat dead code.
Develop production batch: readable multi-source Brain Activity graph, dead synaptic/API path removal, and hardened llm_trader_executor integration.
GET /api/brain/decision-summaryaggregates active position, vector experiences, semantic rules, blocked trades, trade-journal post-mortems, and last response into a synopsis + hierarchical multi-source graph payload.- Brain Activity Decision Pathways panel: labeled hierarchical graph (Position / Memory / Rules / Journal / Decision), synopsis strip, type legend, click-to-detail card.
- Shared
_build_execution_decision()CCXT-ready payload used by both file write and HTTP forward. tests/test_decision_summary_api.py,tests/test_execution_decision_bridge.py.
_save_execution_decisionreturns the written payload;_forward_decision_to_executorreuses it so disk + HTTP stay identical.- Executor network/HTTP failures log full traceback (
exc_info=True); silentexcept: passremoved. PersistenceManager.save_latest_decisionlogs with traceback and re-raises after atomic write failures.httpx>=0.27,<1declared inrequirements.txt.- Panel DOM id renamed
panel-synapses→panel-decision-pathways; README screenshot caption retitled Decision Pathways.
synapse_viewer.jstrade-history BUY/SELL/CLOSE graph consumer (vis-network retained for Decision Pathways only).GET /api/brain/memory+BrainRouter.get_vector_memory+ dashboard cache prefixmemory_*(no back-compat).- Dead legend CSS
.dot.buy/.close/.update.
- Decision summary + static bindings + brain router + server cache.
- Executor bridge unit tests (payload, SKIP HOLD, HTTP forward, error logging, atomic latest_decision write).
- Discord trading-check path remains green with executor API disabled in fixtures.
- Hard-refresh dashboard clients for Decision Pathways JS/CSS cache bust (
main.js?v=6.0,style.css?v=6.3,decision_pathways_panel.js?v=1.1). - Production was briefly stuck loading synopsis because Cloudflare caches
main.js?v=*as immutable and origin still had oldsynapse_viewermajor path undermain.js?v=5.2while HTML already pointed at Decision Pathways markup. - Restart trading bot process to pick up brain router + executor bridge changes.
- Executor HTTP remains optional via
[executor_api];latest_decision.jsonstays as file fallback.
- Executor audit: 10-point security review of
llm_trader_executor(separate repo) completed and pushed tomain. - SPOT_SHORT_ALLOWED (new
.envflag in executor, defaulttrue): SELL signals on spot are now capped to actual held base-asset balance instead of hard-blocked. Whenfalse, any insufficiently-backed SELL is rejected outright. - UPDATE quantity fix:
place_sl_tp_oco()now overrides quantity from the tracked position's real size instead of acceptingquantity=0.0from the LLM decision (which would cancel SL/TP without replacing them). - set_leverage() now called before entry on non-spot markets (previously leverage from the LLM prompt was validated but never applied).
- PositionTracker refactored from single-global to
dict[symbol, Position]— multi-pair ready. - OCO fallback:
create_order('oco')attempted directly with try/except instead of relying onexchange.has['createOrder']['oco'](which crashes on most exchanges becausehasvalues are booleans, not dicts). - UTF-8 stdout forced on Windows to prevent
UnicodeEncodeErrorcrashes from emoji log prints. - Notional check in safety guard uses live ticker price as fallback for market orders (previously
entry_price=Nonewould bypass the check entirely).
- Executor payload format from
_save_execution_decision()is fully compatible — no changes needed on this side. - The executor now clamps SELL quantity to <99% of available base balance. For example, a SELL 6 BTC signal with 1 BTC held executes as 0.99 BTC sell instead of failing.
- Restart executor (
scripts/start.ps1inllm_trader_executor) to pick up changes.
- BlockRun.AI provider (fully optional) — x402 micropayment-based AI provider via
blockrun-llmSDK. Gated behindBLOCKRUN_WALLET_KEYenv var; no-op when unset. llm_analysisfield in post-mortem API response —get_recent_post_mortems()now returns the full LLM analysis text that was already stored but missing from the query result.- 96 new tests: BlockRun provider unit/integration tests, post-mortem API endpoint tests, trading strategy check_position/exit handling tests.
- Dashboard resilience — each panel initializer now has its own try/catch. A single panel failure no longer cascades and kills the entire dashboard.
- SL/TP logging crash —
trading_strategy.pyno longer crashes when formatting a position update withNonestop_loss or take_profit.
- aiohttp 3.13.4 → 3.14.1: Patched 11 CVEs including deserialization RCE (CVE-2026-34993, CVSS 6.4), cross-origin cookie leak (CVE-2026-47265), unbounded pipelined requests DoS (CVE-2026-54273), WebSocket memory limit bypass (CVE-2026-54274), TLS SNI bypass on reused connections (CVE-2026-54275), DigestAuth credential leak via redirect (CVE-2026-54276), HTTP parser
max_line_sizebypass (CVE-2026-54277), zip-bomb unbounded decompression (CVE-2026-54278), host-only cookie persistence downgrade (CVE-2026-54279), mid-disconnect resource leak (CVE-2026-54280), CRLF injection in multipart headers (CVE-2026-50269). - fastapi 0.128.0 → 0.138.0: Unblocks starlette ≥1.x for 4 additional CVEs.
- starlette 0.50.0 → 1.3.1: Patched host header SSRF (CVE-2026-54282), path-based authorization bypass (PYSEC-2026-161), HTTPEndpoint method smuggling via non-standard verbs (CVE-2026-48817), Windows StaticFiles UNC path NTLM leak (CVE-2026-48818, Linux not affected), unbound urlencoded form parsing DoS (CVE-2026-54283).
- python-multipart 0.0.27 → 0.0.31: Patched quadratic-complexity DoS in
;-separated form parsing (CVE-2026-53539), HTTP parameter pollution via;/&parser differential (CVE-2026-53538), negative Content-Length unbounded read (CVE-2026-53540). - lxml 5.4.0 → 6.1.1: Patched XXE via default
resolve_entities=Trueallowing local file reads from untrusted XML input (PYSEC-2026-87). - cryptography 48.0.0 → 48.0.1: Patched statically-linked OpenSSL vulnerability in wheels (GHSA-537c-gmf6-5ccf).
- pydantic-settings 2.14.1 → 2.14.2: Patched out-of-tree symlink read bypassing
secrets_dir_max_size(GHSA-4xgf-cpjx-pc3j). - pynacl 1.5.0 → 1.6.2: Patched libsodium ed25519 point validation (CVE-2025-69277).
- tornado 6.5.6 → 6.5.7: Patched
CurlAsyncHTTPClientcredential leakage via pycurl handle reuse (GHSA-pw6j-qg29-8w7f).
- astro <6.4.6 → 6.4.6: Patched 5 CVEs including reflected XSS via slot name (CVE-2026-50146, HIGH), Host header SSRF in prerendered error page fetch (CVE-2026-54299, HIGH), XSS via unescaped spread props (CVE-2026-54298, MEDIUM), XSS via incomplete
</script>sanitization (CVE-2026-41067, MEDIUM), server island encrypted parameter replay (CVE-2026-45028, LOW). - vite ≤6.4.2 → 6.4.3: Patched
server.fs.denybypass on Windows (CVE-2026-53571, HIGH), NTLMv2 hash disclosure via launch-editor UNC path (CVE-2026-53632, MEDIUM). - js-yaml ≤4.1.1 → 4.2.0: Patched quadratic-complexity DoS in merge key handling via repeated aliases (CVE-2026-53550, MEDIUM).
- esbuild <0.28.1 → 0.28.1: Patched arbitrary file read when running dev server on Windows (GHSA).
- Removed
data_template/tree from public repo. - Cleaned public README, AGENTS.md, and removed outdated CI workflow and stale start scripts.
- Merged
developbranch intomasterfor v1.0 release.
- 1021 pytest passed (Playwright/live excluded — pre-existing).
- pip-audit: 0 fixable vulnerabilities remaining. Only unfixed:
chromadbCVE-2026-45829 (no patch available yet, ChromaDB runs localhost-only — not exploitable). - Dependabot: 40 alerts auto-resolved to
fixedstate.
- Post-mortem analysis on every position close (
src/trading/post_mortem.py): After a position closes, the LLM analyzes what happened (entry reasoning, exit data, market conditions) and extracts an actionable lesson. Produces a structuredPostMortemResultwith verdict, analysis, expected vs actual, and lesson. Fires after the CLOSE row is written to SQLite, wrapped in try/except so failures never break the close flow. - SQLite + FTS5 storage layer (
src/managers/post_mortem_repository.py): Newtrade_post_mortemandtrade_post_mortem_ftstables in the existingtrade_history.db. Thread-safe viathreading.Lockand per-call connections matching theSQLiteTradeHistorypattern. Supports insert, recent listing, keyword search via FTS5 MATCH, and count. Schema isCREATE TABLE IF NOT EXISTS— zero impact on existing tables, no migration needed. - Trade journal injected into brain context (
src/trading/brain_context.py):BrainContextProviderappends the 5 most recent post-mortem lessons as a"### Trade Journal (Recent Post-Mortem Lessons):"section in the system prompt, so the LLM sees past mistakes before every trading decision. - Dashboard Trade Journal tab (
src/dashboard/static/modules/post_mortem_panel.js): New sidebar tab with searchable post-mortem viewer. Displays verdict, symbol, P&L, close reason, and lesson learned per card. Expandable full-analysis details. FTS5 search bar with result highlighting. Updates every 30s in the slow-lane cycle. - Dashboard API endpoint (
src/dashboard/routers/brain.py):GET /api/brain/post-mortems?q=breakout&limit=20returns post-mortems with optional FTS5 keyword search. Error-returning, never crashes.
- LLM response parsing resilience (
src/trading/post_mortum.py): Added rawjson.loads()fallback in_parse_responsewhen the LLM returns plain JSON without markdown fences. The primary extraction path (UnifiedParser.extract_json_block) handles```jsonblocks; the fallback catches model output that skips the fence syntax. - Test timestamp ordering (
tests/test_post_mortem_repository.py): Replacedtime.sleep(1.5)with direct SQL timestamp override, eliminating a test smell. Ordering test now runs in 0.02s instead of 1.5s. - Mock safety in context tests (
tests/test_brain_context_journal.py): Configured all mock return values explicitly (trade_count=0,get_context_for_prompt.return_value="", etc.) to preventMagicMocktruthyness from corruptingBrainContextProvidercontrol flow.
| File | Purpose |
|---|---|
src/managers/post_mortem_repository.py |
SQLite + FTS5 storage (insert, search, recent, count) |
src/trading/post_mortem.py |
PostMortemResult Pydantic model + PostMortemService (LLM orchestration) |
src/dashboard/static/modules/post_mortem_panel.js |
Dashboard frontend module with search and card rendering |
tests/test_post_mortem_repository.py |
10 tests: insert, FTS5 search, ordering, count, error handling |
tests/test_post_mortem_service.py |
6 tests: success, empty/malformed/missing response, LLM exception, repo exception |
tests/test_brain_context_journal.py |
7 tests: journal section present/absent, multi-entry, P&L formatting, error skip |
tests/test_post_mortem_contract.py |
10 tests: Pydantic model validation, empty/missing rejection, extra fields |
| File | Change |
|---|---|
src/trading/trading_strategy.py |
close_position() triggers post-mortem after CLOSE row, before stats recalc |
src/trading/brain_context.py |
Trade journal section injected into get_context() output |
src/trading/brain.py |
post_mortem_repo wired through to BrainContextProvider |
src/dashboard/routers/brain.py |
GET /api/brain/post-mortems endpoint + post_mortem_repo param |
src/dashboard/server.py |
post_mortem_repo threaded into BrainRouter |
src/dashboard/static/index.html |
Trade Journal nav item + tab content panel + search toolbar |
src/dashboard/static/main.js |
Import + slow lane + init for post-mortem panel |
src/dashboard/static/css/panels.css |
Full .pm-* styling for cards, search bar, verdict colors, details |
start.py |
DI wiring for PostMortemRepository + PostMortemService into strategy, brain, dashboard |
- Full pytest (no Playwright):
1060 passed - New test suite:
33 passed in 0.16s - Live LLM validation: end-to-end call via gemini-3.5-flash confirmed prompt → response → parse → store → search
- Ruff lint: all checks passed on new and modified files
- Ticker fetch retries restored (
src/app.py): Applied@retry_async(max_retries=3, initial_delay=1, backoff_factor=2, max_delay=30)to_fetch_current_ticker()and removed the internaltry/except Exceptionthat swallowed all errors before the decorator could see them. Transient network errors, timeouts, and rate limits now retry with exponential backoff; non-retryable exchange errors (e.g.BadSymbol) propagate immediately. The startup ticker fetch (run()) wraps the call in a try/except that logs and continues without a price. - Zero-division guard in notifier (
src/notifiers/base_notifier.py):calculate_stop_target_distances()returns(0.0, 0.0)whencurrent_priceisNoneor<= 0, preventing the cascadingZeroDivisionErrorinsend_position_status. - Skip status on unavailable price (
src/trading/position_status_monitor.py):_loop()andhandle_new_position()now skip the position-status notification when the ticker price is unavailable instead of sending a misleading$0.00.
- Ticker retry tests (
tests/test_ticker_retry.py): Covers retry-then-succeed onRequestTimeout/RateLimitExceeded, exhaustion onClientConnectorError, non-retry onBadSymbol, the zero/None price guard, and the monitor skip-on-no-price behavior.
- Focused pytest:
tests/test_ticker_retry.py tests/test_brain_integration.py -q-> 66 passed.
- Step 5.5 invalidation check (
src/analyzer/prompts/template_manager.py): Replaced the generic "BULL vs BEAR CASE: Which side wins?" with a falsification-based prompt that forces the model to name a specific price level or indicator condition that would prove its signal wrong. Signals without a falsifiable invalidation trigger are rejected (HOLD). - Surprise ratio computation (
src/trading/brain_experience.py): On every closed trade, the system now computessurprise_ratio = |realized_pnl - expected_pnl| / |expected_pnl|where expected P&L is the TP distance at entry. Stored in ChromaDB metadata assurprise_ratio. - Surprise ratio in reflection rules (
src/trading/brain_reflection.py): All three reflection passes (best-practice, anti-pattern/corrective, AI-mistake) now compute the average surprise ratio for the trade group and include it in the rule text. Best-practice rules withavg_surprise > 1.5are flagged as "⚠️ high surprise" so the LLM can distinguish thesis-validated wins from lucky outcomes. - Overridden prompt section
5.5 BULL vs BEAR CASE→5.5 INVALIDATION CHECKin the analysis steps.
template_manager.py: Step 5.5 inbuild_analysis_steps()rewritten from opinion-prompting to falsification-prompting.brain_experience.py:record_closed_trade()computes and persistssurprise_ratioin trade metadata.brain_reflection.py:trigger_reflection(),trigger_loss_reflection(), andtrigger_ai_mistake_reflection()all computeavg_surprisefrom grouped trades and surface it in rule text.
- Focused AST parse:
src/analyzer/prompts/template_manager.py→ OK - AST parse:
src/trading/brain_experience.py→ OK - AST parse:
src/trading/brain_reflection.py→ OK - No breaking test changes: existing
test_prompt_consistency.pyandtest_template_manager.pyunaffected (step 5.5 string not under test assertion).
- Added timeframe-aware semantic-rule influence scoring. Active rules remain physically preserved, but prompt retrieval now ranks by similarity, evidence quality, timeframe freshness, and contradiction penalty.
- Semantic rules now carry lifecycle metadata including
created_at,support_count, validation/contradiction counters, and source timeframe fields. - Closed-trade recording now updates matched semantic-rule validation or contradiction metadata so old rules can be down-weighted by live evidence without age-only deletion.
- Brain prompt context and dashboard active-rule responses now expose concise freshness/evidence fields.
- Focused pytest:
tests/test_vector_memory.py tests/test_vector_memory_pruning_safety.py tests/test_brain_integration.py tests/test_dashboard_brain_router.py -q-> 116 passed. - Full pytest:
tests -q-> 900 passed. - Targeted Ruff on touched trading/dashboard/test files -> passed.
- Removed runtime trade-history JSON compatibility paths. Trade decisions now save to SQLite only, history reads export from SQLite only, and entry-decision lookup no longer scans legacy JSON files.
- Removed SQLite auto-migration constructor support and the one-shot JSON migration helper from the trade-history store.
- Updated tests to seed SQLite directly instead of writing legacy history files.
- Removed old-history fee inference from notifier performance stats; stats now use persisted fee values.
- Updated AGENTS documentation for SQLite-only persistence, persistence-backed cooldown/dashboard paths, active semantic-rule pruning safety, and Windows PowerShell terminal guardrails.
-
SQLite runtime integration gaps closed:
src/dashboard/routers/brain.py:get_vector_memory()now reads trades viapersistence.load_trade_history()(SQLite-backed) instead of directtrade_history.jsonfile reads.src/dashboard/routers/performance.py:get_performance_history()now reads trades through injected persistence instead of direct JSON file reads.src/dashboard/server.py: passespersistenceintoPerformanceRouter.
-
Cooldown guard no longer depends on legacy JSON:
src/trading/guards/cooldown_window.pynow uses injected persistence (get_last_execution_timestamp) instead of disk reads fromtrade_history.json.- Guard now fails closed when persistence is not wired or cannot read execution history, avoiding silent fail-open behavior under persistence failures.
start.pynow wiresCooldownWindowGuard(persistence=persistence)in the production guard pipeline.
-
SQLite API hardening:
src/managers/sqlite_trade_history.py:- validates
order(ASC/DESC) before SQL generation, - clamps/validates pagination inputs,
- adds
get_last_execution_timestamp(actions=("BUY", "SELL"))helper for guard usage.
- validates
src/managers/persistence_manager.py:load_trade_history()now uses SQLite export directly,- adds
get_last_execution_timestamp()facade for DI-friendly guard consumers.
-
ChromaDB pruning policy corrected for semantic safety:
src/trading/vector_memory.py:prune_aged_documents()now parses timestamps as datetimes and preserves active semantic rules (active=True) instead of deleting by age-only policy.
-
Lint cleanup:
scripts/query_trade_history.pyandsrc/managers/sqlite_trade_history.pycleaned up to satisfy Ruff.
-
tests/test_sqlite_trade_history.py:- SQLite initialization coverage,
- query input validation,
- execution timestamp helper behavior.
-
tests/test_vector_memory_pruning_safety.py:- verifies old experience/blocked-trade pruning,
- verifies active semantic-rule preservation,
- verifies malformed timestamp handling.
tests/test_dashboard_brain_router.py: adds persistence-backed trade-history read assertion for vector memory endpoint.tests/test_dashboard_performance_router.py: adds persistence-backed history assertion and updates constructor usage.tests/test_order_governance.py: adds cooldown fail-closed and no-history allow-path assertions.
-
Ruff (targeted):
python -m ruff check src/managers/sqlite_trade_history.py scripts/query_trade_history.py-> passed.
-
Ruff (broad scope):
python -m ruff check src start.py scripts tests-> passed.
-
Pytest (targeted integration set):
pytest tests/test_position_persistence.py tests/test_order_governance.py tests/test_sqlite_trade_history.py tests/test_dashboard_brain_router.py tests/test_dashboard_performance_router.py tests/test_vector_memory_pruning_safety.py -q-> 42 passed.
-
Pytest (pruning safety):
pytest tests/test_vector_memory_pruning_safety.py -q-> 3 passed.
-
Full-suite pytest:
pytest -q-> 895 passed.
data/trading/trade_history.jsonwas migrated intodata/trading/trade_history.db.- Migration inserted 12 records into the SQLite
trade_historytable. - The legacy JSON file was renamed to
data/trading/trade_history.json.migratedand kept as backup.
-
src/managers/sqlite_trade_history.py: SQLite-backed trade history store replacing JSON file accumulation. Provides O(1) INSERT appends, indexed timestamp/symbol/action queries, WAL journal mode with NORMAL synchronous for performance, and aget_stats()method returning aggregate data for the dashboard. -
scripts/query_trade_history.py: CLI utility for querying the trade history SQLite database directly from the terminal. Supportsrecent,search, andstatscommands with filtering by symbol, action, date range, limit/offset pagination, and sort direction. Also works with rawsqlite3command for ad-hoc queries. -
PersistenceManager.validate_loaded_position(): Startup state validation that checkspositions.jsonfor config mismatches (symbol vsCRYPTO_PAIR, unrecognized fields). Logs actionableSTARTUP STATE WARNINGmessages without discarding the position — the operator decides. -
/api/monitor/healthendpoint: Lightweight liveness probe returning{"status": "ok", "timestamp": "..."}with zero I/O. Suitable for Docker healthchecks, systemdExecStartPostprobes, and local watchdog scripts without touching Cloudflare routing. -
VectorMemoryService.prune_aged_documents(): Safe ChromaDB collection maintenance that removes only documents definitively beyond the relevance window (3×_max_age_days). Runs once at startup on all three collections (trading_experiences,semantic_rules,system_constraints_rejections). Uses the existingPRUNE_AGE_MULTIPLIERconstant — at a 4h timeframe, keeps ~168 days of history while preventing unbounded disk/RAM growth.
-
CoinGecko cache TTL (
start.py:365): Changedexpire_after=-1(never expire) toRAG_COINGECKO_UPDATE_INTERVAL_HOURS * 3600seconds (24h by default). Cache entries now expire on the same cadence as the data refresh cycle, preventing unbounded SQLite growth. -
GracefulShutdownManager.show_exit_confirmation(): Added_is_headless()detection — whenDISPLAYenv var is not set ANDsys.stdinis not a TTY (systemd/WSL/Docker), skips ALL blocking prompts (tkinter dialog andinput()) and returnsTrueimmediately. Enables unattended systemd/Wired restarts without hanging. -
TradingStrategy.__init__(): Now callspersistence.validate_loaded_position()after loading an existing position. Any symbol/config mismatches are logged as warnings. -
PersistenceManager:save_trade_decision()now writes to SQLite,load_trade_history()reads from SQLite, andget_entry_decision_for_position()uses SQLite's indexed timestamp range query for O(log n) lookup instead of scanning all JSON records.
CREATE TABLE trade_history (
id INTEGER PRIMARY KEY AUTOINCREMENT,
timestamp TEXT NOT NULL,
symbol TEXT NOT NULL,
action TEXT NOT NULL,
confidence TEXT,
price REAL,
stop_loss REAL,
take_profit REAL,
position_size REAL,
quote_amount REAL,
quantity REAL,
fee REAL,
reasoning TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE INDEX idx_th_timestamp ON trade_history(timestamp DESC);
CREATE INDEX idx_th_symbol ON trade_history(symbol);
CREATE INDEX idx_th_action ON trade_history(action);- Ruff:
ruff check src/ start.py scripts/— All checks passed. - Full pytest: 875 passed (baseline maintained, zero regressions).
-
tests/test_llm_output_corruption.py(15 assertions): Coverage for LLM output corruption, schema violations, and fallback-loop resilience. Scenarios: truncated/malformed JSON, string injection in numeric fields, Infinity/NaN in confidence/price, missing required execution fields (stop_loss, take_profit, entry_price) for BUY/SELL/UPDATE signals, empty choices list, HTML/script injection in reasoning, massive 100KB reasoning field overflow, fallback chain survival when all providers return corrupt data, and mixed corruption-then-recovery patterns. -
tests/test_async_concurrency_race.py(9 assertions): Async concurrency, latency injection, race condition, and state safety tests. Scenarios: slow news-fetch insideasyncio.gather(wall-clock == max not sum), timeout of one gather task not killing siblings, out-of-order completion verification,threading.Lockserialization inVectorMemoryService._encode_embedding, cancelledupdate_if_needednot corruptinglast_updatestate, and double-update serialization viaasyncio.Lock. -
tests/test_api_rate_limiting_backoff.py(16 assertions): HTTP 429 rate-limit, 5xx server error, exponential backoff with jitter, and circuit-breaker boundary tests. Scenarios: rate-limited provider triggers fallback to next provider, all providers rate-limited returns last failure, 503 error retry viaretry_api_call,_add_jitter±25% range verification with 200 samples, jitter randomness proving, zero-delay jitter edge case, exponential delay growth across retries, exhausted retries return last response, retryable-then-success recovery,retry_asynchandling ofClientConnectorError,ccxt.RateLimitExceededexchange error retry, and non-retryableccxt.BadSymbolpropagation. -
tests/test_vector_db_context_poisoning.py(15 assertions): ChromaDB vector store boundaries, context poisoning, and metadata corruption tests. Scenarios: empty news database returns empty context, zero-matching keyword search, empty collection inVectorMemoryService,get_context_for_promptwith zero experiences, perfect-similarity (distance=0.0) edge case,_sanitize_metadatahandling of NaN/Inf/None/lists, missingoutcomekey in ChromaDB metadata, corrupted timestamps,_parse_trade_timestampedge cases, 200-article token budget enforcement, malformed articles missing body, null-title crash proof (production bug fix:_process_article_simplenow handlesNonetitles), UPDATE store with zero PnL, failed initialization graceful False return, NaNsuggested_rrin blocked trades, keyword_search exception isolation inretrieve_context.
src/rag/context_builder.py—_process_article_simple(): Added null-title guard. Previouslyitem.get('title', 'No Title').strip()would crash withAttributeErrorwhen the title field existed but was set toNone. Now falls through to'No Title'when title isNone, matching the existing missing-key behavior. Discovered by chaos testtest_build_context_with_null_title_does_not_crash.
- Ruff:
ruff check src/ tests/— All checks passed. - Full pytest: 884 passed (baseline 829 + 55 new chaos tests, zero regressions).
-
src/utils/decorators.py: Introduced_add_jitter()function adding ±25% random jitter to all exponential-backoff sleep calls. Applied to both_RetryContext._handle_retryable_error()and_ApiRetryContext._wait_and_increment(). Prevents thundering herd when concurrent operations retry simultaneously. -
src/rag/rag_engine.py: Added_last_update_attempttimestamp and_minimum_retry_interval(5 min) to prevent redundant update retries in theretrieve_context()hot path. Skipsupdate_if_needed()when the main loop's update attempt just failed or timed out, reducing context-retrieval latency by avoiding unnecessary news-fetch retries.
-
src/analyzer/analysis_engine.py—_enrich_market_context(): Refactored three sequential API calls (market overview, microstructure, coin details) into parallelasyncio.gather()with isolated error handling per sub-task. Reduces wall-clock latency from ~sum of three API calls to ~max of three API calls (~3x speedup on this path). -
src/rag/rag_engine.py—refresh_market_data(): Refactored three sequential I/O operations (categories update, news fetch, market overview update) into parallelasyncio.gather(). Extracted error-isolated helpers_safe_fetch_news()and_safe_update_market_overview(). Reduces wall-clock latency from sequential to concurrent execution. -
src/platforms/ai_providers/openrouter.py—get_generation_cost(): Offloaded synchronous SDK callclient.generations.get_generation()toasyncio.to_thread(), preventing event-loop blocking during generation-cost lookup.
- Ruff:
ruff check src/passed. - Full pytest: 829 passed (baseline maintained, zero regressions).
-
src/analyzer/formatters/market_formatter.py: AbsorbedMarketPeriodFormatter— itsformat_market_period_metrics()and_format_indicator_changes_compressed()methods now live directly onMarketFormatter. Removed theperiod_formatterconstructor parameter andMarketPeriodFormatterimport.MarketFormatterno longer acts as a pass-through carrier for a sub-formatter; it owns period formatting directly. -
src/analyzer/prompts/prompt_builder.py: Replaced leakyself.period_formatter = market_formatter.period_formatterwith direct callself.market_formatter.format_market_period_metrics(). Eliminates the reach-through abstraction wherePromptBuilderreached intoMarketFormatterto grab a sub-component. -
start.py: RemovedMarketPeriodFormatterconstruction and injection from_provision_analyzer_layer(). RemovedMarketPeriodFormatterimport. -
src/analyzer/__init__.py: Replaced stale multi-line docstring referencing non-existentcore/,data/,calculations/subdirectory layout. Removed duplicate comment header. -
src/analyzer/formatters/__init__.py: RemovedMarketPeriodFormatterre-export.
src/analyzer/formatters/market_period_formatter.py: Deleted. All 109 lines of its logic folded intoMarketFormatter— eliminated the leaky abstraction wherePromptBuilderwas reaching throughMarketFormatterto grab a separately-injected sub-formatter.
tests/test_market_period_formatter.py: ImportsMarketFormatterinstead of the deletedMarketPeriodFormatter; test logic unchanged.tests/test_prompt_builder.py: Removedmarket_formatter.period_formatter = MagicMock()fixture line (no longer needed).tests/test_prompt_context_helpers.py: Same fixture cleanup.
- Ruff:
ruff check src/ start.pypassed. - Full pytest: 829 passed (baseline maintained, +13 over previous 816).
- 1 file deleted, 9 files modified.
- Net: -66 lines, -1 file.
src/indicators/base/technical_indicators.py: ChangedTechnicalIndicatorsfrom composingIndicatorBaseviaself._base(composition) to directly inheriting fromIndicatorBase. Eliminated 5 trivial delegation properties (open,high,low,close,volume) and theget_data()pass-through method — all now inherited. Replaced 77self._base.calculate_indicator(...)calls withself.calculate_indicator(...). Removed unusedUnionandpandasimports.
- No test changes needed —
TechnicalIndicatorsexposes the identical API through inheritance.
- Ruff:
ruff check src/passed. - Full pytest: 829 passed (baseline maintained).
- 1 file modified.
- Net: -61 lines, -2 files cumulative this session.
src/analyzer/analysis_result_processor.py:AnalysisResultProcessor.__init__now requirestrend_validator: TrendValidatorandquality_scorer: PatternQualityScoreras explicit constructor parameters instead of constructing them internally. Removes the last internal DI violation in the analyzer layer.start.py: Composition root now instantiatesTrendValidator()andPatternQualityScorer()inline at theAnalysisResultProcessorconstruction site in_provision_analyzer_layer().src/utils/token_counter.py: RetiredModelPricing.__new__singleton pattern (_instance,_pricingclass-level state,__new__override). EachModelPricing()instance now loads pricing fromconfig/model_pricing.jsonindependently. Publicget_cost()API is unchanged.AGENTS.md: Removed stalefactories/entry from the project-structure tree (source files were already deleted in Pass 2). Replaced the cross-platform Linux/macOS/Windows command matrix and hardcoded absolute Windows paths with a two-line "Operator Commands" pointer toREADME.md. Terminal guardrail policy rules are retained.README.md: Removed stalefactories/entry from the directory structure description; replaced it withutils/. Replaced single barepytest tests/command in the Testing section with a concise relative-path command block covering pytest, ruff, and mypy for both Windows and Linux/macOS.
src/factories/__pycache__/and the now-emptysrc/factories/directory: bytecode residue from the factory modules deleted in Pass 2 is gone.
tests/test_trend_validator.py: Updated 4AnalysisResultProcessorconstruction sites inTestProcessorIntegrationto passtrend_validator=andquality_scorer=keyword arguments.
- Pylance (
get_errors): 0 diagnostics workspace-wide. tests/test_model_pricing.py: 4 passed.- Full
pytest tests -q --tb=short: run in progress at time of entry; see terminal for authoritative result. ruff check src tests start.py: run in progress at time of entry; see terminal for authoritative result.
AGENTS.md: Added explicit instruction-authority contract making AGENTS files canonical across IDEs/harnesses.AGENTS.md: Added terminal guardrails and Windows command examples so execution policy is no longer IDE-specific.AGENTS.md: Added documentation-governance checklist and anti-drift rule to block reintroduction of tool-specific policy docs.
- Deleted IDE/harness-specific instruction files:
.github/copilot-instructions.md.github/instructions/terminal-guardrails.instructions.mdCLAUDE.md.windsurfrules
- Kept
.github/workflows/compatibility_manual_main.ymlas CI execution configuration only; it is not an instruction-authority source.
- Removed 30+ private
TradingBrainServicedelegation wrappers that only forwarded to extracted collaborators and had no live production or test call sites. - Deleted
src/notifiers/filehandler_components/after folding its four single-use tracking, persistence, scheduling, and deletion classes intoDiscordFileHandler. - Deleted
src/contracts/model/risk protocol files and the obsolete contracts README;ModelManagerandRiskManagerare now used as concrete injected services. - Removed unused
AnalysisEngineconstructor dependencies for CoinGecko and Alternative.me; those clients remain wired only where they are actually used.
src/notifiers/filehandler.py: Flattened Discord message tracking into one class that owns JSON persistence, expiry scanning, retry-backed deletion, and cleanup task scheduling.start.py: Simplified Discord file-handler construction andAnalysisEngineprovisioning after removing unused dependency layers.src/app.py,src/analyzer/analysis_engine.py,src/analyzer/analysis_result_processor.py,src/managers/model_manager.py,src/managers/risk_manager.py, andsrc/trading/trading_strategy.py: Replaced single-implementation protocol annotations/inheritance with direct concrete service types.AGENTS.md: Removed the stalesrc/contractsproject-structure entry.
- Focused brain/vector-memory pytest:
97 passed in 0.42s. - Focused analyzer/app wiring pytest:
4 passed in 1.56s. - Focused Discord notifier pytest after flattening:
7 passed in 1.12s. - Focused trading/risk/response pytest after protocol removal:
69 passed in 2.15s. - Full pytest validation is not claimed for this pass; the attempted PowerShell capture command was malformed (
^Uprefix and$pytestOutvariable failure), making itsPYTEST_EXIT:0output unreliable. - Full ruff validation:
ruff check src tests start.pypassed. - Pylance (
get_errors): no errors on modified files or workspace-wide final check.
- Deleted
src/analyzer/pattern_engine/pattern_engine.py—PatternEngine.detect_patterns()always returned{}and was never wired after its Numba deprecation. - Deleted
src/analyzer/pattern_engine/pattern_matchers.py,swing_detection.py,trendline_fitting.py— the three Numba JIT support files thatPatternEnginedepended on; now fully unreachable. - Deleted
src/platforms/ai_providers/mock.py—MockClient(133 LoC) was never instantiated anywhere in production or test code. - Deleted
src/factories/provider_factory.py,data_fetcher_factory.py,position_factory.py, andsrc/factories/__init__.py— all three factories were single-method wrappers that added indirection without logic; the module is now empty.
src/analyzer/pattern_engine/__init__.py: Stripped to a single re-export ofChartGenerator; removed the 12 dead symbol exports for the now-deleted pattern-engine stack.src/analyzer/pattern_analyzer.py: RemovedPatternEngineconstructor dependency and itsdetect_patterns()call;warmup()now uses a fixed 64-sample count instead of deriving it from the dead engine'slookback; removed unreachableget_all_patterns()method.src/analyzer/analysis_engine.py: InlinedDataFetcher(exchange, logger)construction ininitialize_for_symbol(); removeddata_fetcher_factoryconstructor parameter and all references.src/trading/trading_strategy.py: InlinedPosition(...)construction in_open_new_position(); replacedposition_factory.create_updated_position()call in_update_position_parameters()withdataclasses.replace(self.current_position, stop_loss=..., take_profit=...); removedposition_factoryconstructor parameter.src/managers/provider_types.py: RemovedProviderClients.from_factory_dict()classmethod that was only called by the now-deletedProviderFactory.start.py: ReplacedProviderFactoryusage with inlineGoogleAIClient,OpenRouterClient,LMStudioClientconstruction in_provision_model_layer(); removedDataFetcherFactoryfrom_provision_utilities(); removedPositionFactoryandPatternEnginefrom_provision_analyzer_layer()and_provision_trading_layer().
- Updated 5 test files (
test_trading_strategy_branches.py,test_trading_strategy_frictions.py,test_trading_strategy_process_analysis.py,test_order_governance.py,test_edge_cases_feedback.py) to removeposition_factoryconstructor arg and addentry_price/volatility_levelfields toRiskAssessmentmocks that now flow through inlinePosition(...)construction. - Position-update assertions changed from
factory.create_updated_position.assert_called_once()to directstrategy.current_position.stop_loss == ...attribute checks.
- Full pytest: 816 passed (baseline maintained).
- Full ruff validation:
ruff check src tests start.py— all checks passed. - Pylance (
get_errors): no errors on any modified file.
- src/app.py and start.py: Replaced the wide
CryptoTradingBotconstructor surface with a compactBotServicesbundle and moved position-monitor provisioning into construction via a factory callback. - src/analyzer/technical_calculator.py: Inlined technical indicator construction and removed the redundant factory layer.
- src/analyzer/prompts/prompt_builder.py: Folded analyzer prompt context-section helpers directly into
PromptBuilder, keeping prompt assembly in one owner instead of a pass-through collaborator. - src/logger/logger.py, src/utils/profiler.py, and tests/conftest.py: Removed broad config-loader test monkeypatching by making config singleton access lazy and local to fallback paths.
- src/trading/trading_strategy.py and src/trading/guards/pipeline.py: Simplified guard/audit ownership so
TradingStrategyrecords audit events andGuardPipelineonly evaluates guards. - src/config/loader.py and config consumers: Retired the oversized config protocol type surface in favor of concrete config injection with type-check-only hints.
- Removed
TechnicalIndicatorsFactoryandsrc/factories/technical_indicators_factory.py. - Removed
src/config/protocol.pyafter replacingConfigProtocolannotations. - Removed analyzer
ContextBuilderandsrc/analyzer/prompts/context_builder.py. - Removed unused prompt delta-alert helper coverage along with the helper itself.
- Removed unused order lifecycle states/history (
APPROVED,CANCELLED,state_history) and the unused guard-pipeline audit compatibility shim.
- Focused pytest after final pass:
138 passed in 1.86s. - Full pytest after final pass:
816 passed in 27.11s. - Full ruff validation:
ruff check src tests start.pypassed. - Targeted stale-symbol scan found no live Python/Markdown references to the removed protocol, factories, prompt context builder, guard audit shim, or old order lifecycle states.
- Hardened INI loading to strip inline comments and disable percent interpolation for literal percentage text in configuration values or comments.
- Sanitized non-finite statistics values before JSON persistence and rejected NaN/Infinity numeric payloads in AI parsing, position extraction, and market cache timestamp checks.
- Added regression coverage for config inline comments, signal-direction disambiguation, cooldown cache invalidation after execution, and nested tuple restoration for position confluence factors.
- Added hidden-runtime-failure tests for non-finite persisted statistics, malformed AI numeric fields, non-finite position extraction values, and corrupt market overview timestamps.
- Added a default pre-execution order guard pipeline with configured-pair, explicit over-cap position size, and cooldown guards.
- Added in-memory audit records for order intent creation, guard checks, approval, rejection, and execution lifecycle events.
- Added regression coverage for order lifecycle transitions, guard audit capture, guard rejection handling, max-position validation, and no-guard execution telemetry.
TradingStrategynow wraps new position entries in order lifecycle/audit telemetry while the composition root injects the guard pipeline by default.- Replaced optional extra symbol allow-list configuration with fixed configured-pair enforcement.
- Removed stale Google sampling plumbing from the Google config/provider path and kept Gemini on model defaults.
- Added a new static website workspace under
website/using Astro + Tailwind for a standalone engineering landing page. - Added production-style simulated telemetry visuals (SVG/CSS panels) for dashboard, stream, and vector-memory sections without depending on outdated screenshot assets.
- Updated architecture documentation in
docs/llm_agent_documentation.mdto match the real staged startup flow (SingleInstanceLockplus sequencedCompositionRoot.build_dependencies()provisioning). - Updated
docs/detailed_file_documentation.mdwith the modular trading-brain collaborator map (brain_context.py,brain_experience.py,brain_exit_profiles.py,brain_patterns.py,brain_reflection.py) and indicator semantic translation details. - Updated
docs/INDEX.mdwith a compact documentation map linking architecture docs, detailed file docs, cache playbook, refactoring status, README, changelog, and website workspace. - Updated
README.mdto include landing/deployment context, refreshed architecture tree for modular brain collaborators, and explicit paper-trading scope posture.
- Removed outdated dashboard screenshot dependencies from public-facing release messaging in README and website rollout materials.
- Completed cleanup of deprecated legacy runtime structure references in updated release-facing documentation.
- .github/workflows/compatibility_manual_main.yml: Added a low-cost manual compatibility workflow with three tiers: Linux full tests, Windows medium static checks, and macOS smoke syntax checks.
- scripts/start_script.ps1: Moved Windows main-branch startup script into
scripts/and updated it to resolve repository-rooted paths after relocation. - scripts/start_script_linux.sh: Added Linux startup script for main branch with venv creation, optional dependency installation, and
start.pylaunch support. - scripts/start_script_macos.sh: Added macOS startup script for main branch with venv creation, optional dependency installation, and
start.pylaunch support. - README.md: Documented cross-platform startup script usage from both the repository root and the
scripts/directory.
- .gitignore: Removed the global
*.ps1ignore rule so PowerShell scripts are tracked normally without exception rules. - start_script.ps1: Removed root-level script in favor of the new tracked path under
scripts/. - scripts/start_script.ps1, scripts/start_script_linux.sh, and scripts/start_script_macos.sh: Made Git branch checkout best-effort so startup can continue when Git is not available on
PATH. - src/utils/graceful_shutdown_manager.py: Exit confirmation now falls back to a terminal prompt when a Tkinter GUI dialog cannot be shown, improving Ctrl+C behavior on Linux/macOS and headless sessions.
- src/app.py: Removed the direct per-cycle
send_trading_decision()call so analysis cycles no longer emit a separate decision embed in addition to the analysis notification payload. - src/notifiers/notifier.py: Kept narrative reasoning delivery via existing
send_message()chunking behavior (multiple Discord messages when reasoning exceeds Discord limits). - tests/test_app_discord_message_flow.py: Added orchestration-level regression test verifying the trading loop uses analysis notifications without sending an extra decision embed.
- config/model_pricing.json: Corrected
gemini-3.5-flashpricing to $1.50 input / $9.00 output per million tokens (was $0.50/$12.00). Addedgoogle/gemini-3.5-flashto the OpenRouter reference section. Added deprecation note togemini-2.0-flash(Google shutting down June 1 2026). Source: ai.google.dev/pricing (2026-05-19). - tests/test_model_pricing.py: Updated
gemini-3.5-flashpricing regression assertion from $12.50 to $10.50.
- requirements.txt: Pinned the beta OpenRouter SDK to
openrouter==0.9.1. - src/config/loader.py and src/config/protocol.py: Switched default model config output to canonical
frequency_penaltyandpresence_penaltynames while preserving deprecatedfreq_penaltyandpres_penaltyINI aliases. - src/platforms/ai_providers/openrouter.py and src/managers/provider_orchestrator.py: Wired OpenRouter
server_urlconstruction, explicit SDK cleanup, and a one-retry fallback model for validation or rate-limit failures. - src/platforms/ai_providers/google.py: Kept code execution tools limited to known Gemini 3 Flash+ models.
- config/config.ini and config/config.ini.example: Clarified OpenRouter fallback/base URL behavior and canonical penalty names.
- README.md: Removed active legacy Google sampling from the normal configuration snippet and documented it as Gemini 1.x/2.x-only.
- config/model_pricing.json: Updated pricing metadata date and added the active
gemini-3.5-flashGoogle Studio model pricing reference.
- requirements.txt: Raised the Google GenAI SDK minimum version to
google-genai>=2.4.0. - src/platforms/ai_providers/google.py: Migrated
ThinkingConfigto usetypes.ThinkingLevelenum values (MINIMAL,LOW,MEDIUM,HIGH) instead of raw strings to match SDK 2.4 API. - src/platforms/ai_providers/google.py: Switched
GenerateContentConfigconstruction tomodel_validate()for forward-compatible field assignment. - src/platforms/ai_providers/google.py: Added SDK-native
errors.APIError-aware thinking fallback handling via_should_retry_without_thinking()and explicit async SDK client cleanup inclose(). - tests/test_google_ai_provider.py: Added focused Google provider tests for generation config, thinking fallback, chart-image request wiring, and async cleanup.
- config/config.ini and config/config.ini.example: Removed Google sampling overrides from
[model_config]and aligned with Gemini 3.x model-default behavior. - src/config/loader.py: Removed Google sampling-key mapping from
_google_model_config; Google runtime config now forwards onlymax_tokens,thinking_level, andgoogle_code_execution. - src/platforms/ai_providers/google.py:
GenerateContentConfigno longer sendstemperature,top_p, ortop_kfor Google requests, preventing deprecated/unsupported sampling-parameter usage on Gemini 3.5 Flash.
- src/analyzer/prompts/prompt_builder.py: Added
| Noneto all eight injected-dependency constructor parameters (TechnicalCalculator,FormatUtils,MarketOverviewFormatter,LongTermFormatter,TechnicalFormatter,MarketFormatter,TemplateManager,ContextBuilder) to resolve Pylance type errors. - src/analyzer/prompts/prompt_builder.py: Guarded
context_builder.build_market_data_section()call withif context.ohlcv_candles is not Noneto satisfynp.ndarray(non-optional) parameter contract. - src/analyzer/prompts/prompt_builder.py: Replaced
context.current_price(typedfloat | None) withcontext.current_price or 0.0in theformat_long_term_analysis()call. - src/analyzer/prompts/prompt_builder.py: Added
if self.context is None: return Falseguard at the top of_has_advanced_support_resistance()to fix"technical_data" is not a known attribute of NonePylance error. - tests/test_prompt_builder.py: Added
config=SimpleNamespace(MODEL_VERBOSITY="high")to_make_prompt_builder()fixture to match updated constructor signature. - tests/test_prompt_consistency.py: Removed leftover
>>>>>>> bug-checkmerge-conflict markers and orphaned dead class body (duplicate docstring andsetup_method) introduced by the prior merge commit.
- src/analyzer/prompts/template_manager.py: Updated previous-response sanitization to use verbosity-scaled retention caps (
low=1500,medium=3000,high=4500) so continuity context preserves more technical narrative while still stripping prompt/schema artifacts. - src/analyzer/prompts/template_manager.py: Added explicit exclusion of prior news/sentiment lines from continuity context (for example
NEWS & MACRO,NEWS,SENTIMENT,MARKET SENTIMENT) to restore technical-only carryover semantics between loops. - src/analyzer/prompts/template_manager.py:
build_system_prompt()now passes normalized model verbosity into the sanitizer so continuity size is deterministic per verbosity level.
- tests/test_prompt_consistency.py: Added regression coverage for preserving non-labeled analytical continuity lines and verifying low-vs-high retention cap scaling.
- tests/test_prompt_consistency.py: Added regression coverage proving news/sentiment lines are excluded from prior-context continuity while technical lines remain.
- config/config.ini and config/config.ini.example: Set
[rag] article_max_tokensto1000for runtime and example defaults. - src/config/loader.py: Updated
RAG_ARTICLE_MAX_TOKENSfallback default from256to1000so missing-config behavior matches runtime target. - src/rag/context_builder.py: Removed hardcoded total-context default (
2000) frombuild_context(). Whenmax_tokensis omitted, it now resolves from config asRAG_ARTICLE_MAX_TOKENS * RAG_NEWS_LIMIT, while preserving strict per-article limiting viaRAG_ARTICLE_MAX_TOKENS. - src/rag/article_processor.py: Removed hardcoded
[:10000]body truncation indetect_coins_in_article(), so coin detection scans full article body instead of silently clipping long articles. - src/rag/rag_engine.py: Clarified retrieval-limit docstring contract that default total budget is derived from per-article config and article count.
- tests/test_article_processor_contract.py: Regression test proving late-body ticker mentions (beyond 10k chars) are still detected.
- tests/test_rag_engine_retrieval_contract.py: Contract test for config-derived default retrieval budget.
- tests/test_rag_context_builder_contract.py: Contract test verifying
build_context()default budget resolves from config and passes per-article cap consistently.
- src/trading/stop_loss_tightening_policy.py (new):
StopLossTighteningPolicy— single authoritative gate for SL tightening decisions. Replaces inline executor logic with a deterministic, side-effect-free policy class. Evaluates tightening eligibility from per-timeframe config thresholds (scalping/intraday/swing/position), with optional brain override clamped within a configurable[floor, ceiling]range. Returns aTighteningEvaluationdataclass with full decision metadata. - config/config.ini.example: Seven new keys in
[risk_management]documentingsl_tightening_scalping,sl_tightening_intraday,sl_tightening_swing,sl_tightening_position,sl_tightening_floor,sl_tightening_ceiling, andsl_tightening_min_samples. - tests/test_stop_loss_tightening_policy.py (new, 25 tests): Covers timeframe bucket defaults,
from_config(), LONG/SHORT tightening allow/reject, zero TP distance, missing current price, brain override with sufficient/insufficient samples, floor/ceiling clamping, and all fallback paths.
- src/config/loader.py and src/config/protocol.py: Seven new typed properties for
SL_TIGHTENING_*config keys. - start.py: Single
StopLossTighteningPolicyinstance provisioned in_provision_trading_layer()and injected into bothTradingBrainServiceandTradingStrategy. - src/trading/trading_strategy.py: Replaced hardcoded inline tightening progress guard with
policy.evaluate_update(); blocked events recorded viavector_memory.store_blocked_trade(guard_type="sl_tightening"); blocked events now include position identity metadata (position_id,position_entry_trade_id,position_entry_timestamp);_last_sl_tightening_evaluationinstance attribute captures the accepted evaluation and forwards it tobrain_service.track_position_update();get_position_context()now renders an## SL Tightening Policysection showing effective threshold, current progress, and eligibility. - src/trading/brain.py:
track_position_update()acceptstightening_evaluation: TighteningEvaluation | Noneandtimeframe_minutesand forwards them to the recorder.get_dynamic_thresholds()now populates a nestedsl_tighteningdict withbase_threshold,effective_threshold,effective_threshold_pct, andsourcealongside existing flat keys. - src/trading/brain_experience.py:
track_position_update()stores position identity (position_id,position_entry_trade_id,position_entry_timestamp), SL/TP values, distance percentages, timeframe bucket, and full policy evaluation metadata.record_closed_trade()stores position identity fields to enable update–close pairing. Added_timeframe_bucket()static helper. - src/trading/brain_context.py:
get_dynamic_thresholds()now preserves the nestedsl_tighteningpayload fromcompute_optimal_thresholds(). - src/trading/vector_memory_analytics.py:
compute_optimal_thresholds()passes the full raw Chroma snapshot to the new_learn_sl_tightening_threshold()method. Added_learn_sl_tightening_threshold(): pairs accepted SL-tightening UPDATE records with their eventual WIN/LOSS close outcomes, deduplicates to one update per position, scans candidates[0.05 … 0.40], selects the lowest with positive expectancy, and stores the result underthresholds["sl_tightening"]. - src/analyzer/prompts/template_manager.py: Replaced two hardcoded
"50%+"thresholds in the system prompt and response template with dynamic rendering fromdynamic_thresholds["sl_tightening_pct"]; falls back to generic guidance when the key is absent. - src/analyzer/prompts/prompt_builder.py:
build_system_prompt()now receivesdynamic_thresholdsso the effective tightening threshold is visible in the system prompt. - tests/test_brain_integration.py: Added
TestTrackPositionUpdateWithPolicy(recorder forwarding) and extendedTestGetDynamicThresholdswith nestedsl_tighteningpayload tests (config-source fallback, brain-source override, flat/nested key parity). - tests/test_vector_memory.py: Added four tests under
TestAnalyticsAndThresholdsfor_learn_sl_tightening_threshold: paired wins learn threshold, below min-samples no emission, no close pairs no emission, all-loss expectancy no emission. - tests/test_trading_strategy_branches.py: Updated four SL tightening tests to inject
StopLossTighteningPolicyinstances; renamedtest_not_is_tightening_but_generic_change→test_sl_tightening_no_current_price_rejectedto match new safety-reject behavior. - tests/test_prompt_consistency.py: Updated
test_update_progress_rule_has_no_competing_percentage_thresholdsto assert the static50%+string is gone and"hybrid tightening policy"is present.
- trading_strategy.py: Centralized trade-decision recording so saved BUY/SELL/UPDATE/CLOSE decisions also refresh short-term trading memory.
- trading_strategy.py: Close-time brain learning now runs through a thread offload after the close decision, statistics rebuild, and position clear are persisted.
- trading_strategy.py and dashboard_state.py: Trade-close brain learning now emits dashboard lifecycle notifications and invalidates brain, position, rule, memory, vector, performance, and statistics caches.
- vector_memory.py: Added serialized embedding-model access and stricter Chroma metadata sanitation for non-finite and unsupported values.
- dashboard/routers/brain.py: Moved vector detail retrieval, stats, and sorting work off the async route thread and made legacy numeric metadata sorting safe.
- dashboard/routers/brain.py: Added brain lifecycle and refresh endpoints plus structured risk-management data in the position payload while preserving existing flat fields.
- dashboard/static: Added overview SL/TP execution policy badges, brain lifecycle status, vector freshness, trade-friction rendering, and safer legacy metadata formatting.
- persistence_manager.py: Entry-decision lookup now filters by symbol when available and chooses the nearest timestamp match; position cache updates only after successful disk writes.
- indicator_classifier.py and brain.py: Corrected
ExitExecutionContexttype contracts used by trading brain context building. - brain.py: Split the monolithic trading brain into focused collaborator classes while keeping
TradingBrainServiceas the stable public facade and preserving the publicvector_memoryaccess path. - brain_context.py, brain_experience.py, brain_exit_profiles.py, brain_patterns.py, and brain_reflection.py: Extracted prompt-context/threshold lookup, experience recording, SL/TP exit-profile normalization, trade-pattern diagnostics, and semantic-rule rebuild logic into cohesive modules.
- indicator_classifier.py: Preserved direct mandatory config attribute access for SL/TP execution settings; tests now supply required config fields instead of relying on missing-attribute fallbacks.
- .github/skills/refactor/SKILL.md: Clarified refactor validation guidance to avoid repeatedly rerunning already-green suites unless relevant code changed or a final validation boundary is reached.
- data_utils.py:
SerializableMixin.from_dict()now restores tuple fields from serialized lists. - prompt_builder.py: Added
_previous_context_contains_stale_prompt_rules()to detect when old prompt contract text leaks into continuity context, protecting against schema/format instructions from corrupting future analyses.
- test_brain_integration.py (+86): Brain lifecycle, refresh endpoints, cache bypassing, and memory refresh after saved decisions.
- test_dashboard_brain_router.py (+118): Risk payload, lifecycle data, confidence parsing, brain status/memory extraction from JSON snapshots.
- test_dashboard_server_cache.py (+33 new): Cache headers, server cache invalidation, blocked-trade routing paths.
- test_dashboard_static_bindings.py (+29 new): Static HTML/JavaScript bindings, SL/TP badges, lifecycle status, vector freshness rendering.
- test_data_utils_serialization.py (+16 new): Tuple field serialization/deserialization in
SerializableMixin.from_dict(). - test_edge_cases_feedback.py (+99): Updated to use
MarketConditionsdata model for market context across edge case scenarios. - test_indicator_classifier.py (+25): Mandatory config attribute access for SL/TP execution settings.
- test_position_persistence.py (+60 new): Entry-decision lookup with symbol filtering, cache updates after successful disk writes, write failure handling.
- test_prompt_consistency.py (+137 new): Comprehensive coverage for sanitization of continuity context, stale prompt-section removal, wording consistency, HOLD/UPDATE semantics.
- test_prompt_linting.py (+22 new): Stale prompt-rules detection and sanitization coverage.
- test_risk_manager_frictions.py (+23): Guard types friction generation, delta calculations, mandatory key validation.
- test_trading_strategy_branches.py (+111): Market conditions validation, decision-making processes, friction capture integration.
- test_trading_strategy_frictions.py (+4): Trading strategy friction reporting and persistence paths.
- test_trading_strategy_process_analysis.py (+18): Analysis processing and market condition handling.
- test_vector_memory.py (+47): Non-finite metadata sanitation, complex metadata handling, Chroma store validation.
- Regression coverage and fixture updates for mandatory SL/TP config contracts in indicator classification and trading-strategy friction capture.
- Dashboard regression tests for lifecycle/risk payloads, brain refresh cache invalidation, cache headers, blocked-trade routing, and static frontend bindings.
- trend_validator.py: New module that cross-checks LLM-reported
strength_4h/dailyagainst computed ADX indicators. - pattern_quality_scorer.py: New deterministic pattern quality scoring module using 4-component scoring from actual pattern detection results.
- Integrated trend/pattern validation into
AnalysisResultProcessor._validate_llm_claims()so validation runs on every analysis cycle. - 38 TrendValidator tests (100% coverage) validating ADX cross-checks and strength assertions.
- 34 PatternQualityScorer tests (90% coverage) validating deterministic scoring logic.
- 36 TradingStrategy branch tests (+22pp coverage increase to 73% overall).
- tests/test_risk_manager_frictions.py: Comprehensive friction reporting tests validating generation of friction reports across guard types (max_position_size, max_concurrent_positions, etc.) with correct delta calculations.
- tests/test_trading_strategy_friction_capture.py: Friction capture and persistence tests ensuring frictions from RiskManager are correctly stored, retrieved, and handled on storage failures.
- Enhanced existing test fixtures by adding
scoring_policyandenrichermocks where necessary to support new test requirements.
- RiskManager: Verified all mandatory keys are present in friction reports and that parameters are correctly propagated during friction storage.
- TradingStrategy: Ensured frictions are persisted correctly and failures in storage are handled gracefully with appropriate logging.
- template_manager.py: Sanitized previous-analysis continuity text so old response-format/schema instructions cannot be reintroduced under
PREVIOUS ANALYSIS CONTEXT. - template_manager.py: Previous decision snapshots now use the last valid fenced
analysisJSON block, avoiding schema/example JSON when a response contains multiple fenced blocks. - template_manager.py: Clarified that markdown-heading restrictions apply to the model output only, and made HOLD/open-position and UPDATE semantics more explicit.
- prompt_builder.py: Added preflight warning detection for stale prompt instructions leaking into previous-analysis context and made untrusted-context linting robust to wording variants.
- test_prompt_consistency.py: Regression coverage for previous-context sanitization, stale prompt-section removal, output-heading wording, HOLD semantics, and UPDATE progress wording.
- template_manager.py: Compressed response template by ~60 lines through markdown tables, reduced conditional JSON rules, simplified trend/position/risk/conflict sections, and streamlined output format.
- prompt_builder.py: Removed all-caps directives (CRITICAL→directive, MUST→must) and reduced system prompt by ~30 lines for Flash model clarity.
- trading_strategy.py: Added three critical code guards to prevent SL tightening death spiral: (1) reject SL tightening until price moves 15%+ toward TP (was: immediate tightening), (2) reject entries with R/R < 1.5, (3) cap UPDATE frequency: 1 per 8h for position trades, 2 per swing, 4 per scalping (was: every 4h candle).
- risk_manager.py: Increased minimum SL from 0.5% to 1.0% (below 4H ATR moving average) to reduce micro-losses and preserve account.
- Config (untracked): Brain learning reset from 20 consecutive losing trades; soft exit policy enabled; max position size capped at 10%; increased thinking depth for Flash model.
- Root Cause: SL tightening on every update eliminated TP hits (0/20 in previous cycle, 4.2 updates/trade on average).
- Solution Impact: Code guards now prevent premature SL moves; UPDATE frequency cap reduces noise; R/R check prevents underwater entries; simplified prompts reduce token waste.
- Updated
test_template_manager.py(+61 lines) with coverage for compressed template formats, markdown table rendering, and simplified rule sections.
- All 56 tests pass after template simplification and guard implementation.
- No regressions in entry/exit logic validation.
- Prompt simplifications reduce token usage for more efficient model processing.
- prompt_builder.py: Removed
_detect_minimal_context()and_minimal_contextflag entirely. All prompt sections now render unconditionally — the feature was dead code (MINIMAL_CONTEXT config key never existed). Removedgetattr/hasattrcalls on config. - notifier.py: Replaced
getattr(exc, "status", None)withisinstance(exc, discord.HTTPException)type-narrowing. - crawl4ai_enricher.py: Replaced all 6
getattr()calls with direct attribute access. Removed_markdown_value()helper. Crawl4AI objects have a documented API contract. - dashboard/server.py: Replaced
getattr(response, "body", b"")with try/except AttributeError. - dashboard/routers/brain.py: Replaced
getattr(self.config, "TIMEFRAME", "unknown")with direct access + try/except fallback (2 sites). - rss_primitives.py: Removed 14 decorative section separator headers.
- crawl4ai_enricher.py: Removed 4 decorative section separator headers.
- test_discord_notifier_rate_limit.py:
FakeDiscordHTTPErrornow inherits fromdiscord.HTTPException, matching production hierarchy.
- config/protocol.py:
Dict[str, str]→dict[str, str],Dict[str, Any]→dict[str, Any]. Removed unusedDictimport. - contracts/model_contract.py: Full modernization.
Optional[str]→str | None,List[Dict[str, str]]→list[dict[str, str]],Union[io.BytesIO, bytes, str]→io.BytesIO | bytes | str,Tuple[str, str]→tuple[str, str]. RemovedOptional,Union,Tuple,Dict,Listimports. - config/loader.py:
Dict[str, str]→dict[str, str],Dict[str, Any]→dict[str, Any]. Removed unusedDictimport. - src/app.py: All 11
Optional[X]→X | None, allDict[str, Any]→dict[str, Any]. RemovedOptionalandDictimports.
_detect_minimal_context()and_minimal_contextfromPromptBuilder._markdown_value()fromcrawl4ai_enricher.py.- 18 decorative section separator headers across 2 files.
- context_builder.py:
ArticleScoringPolicyis now injected via constructor (scoring_policyparameter) instead of being constructed internally fromconfig. The composition root (start.py) now creates and wires it. - rss_provider.py:
Crawl4AIEnricheris now injected via constructor (enricherparameter) instead of being constructed internally fromconfigvalues. The composition root now creates and wires it. - start.py: Added construction of
ArticleScoringPolicyandCrawl4AIEnricherin the DI wiring layer, passed toContextBuilderandRSSCrawl4AINewsProviderrespectively. Removed stale duplicate import. - test_rss_provider_contract.py: Added
enricher=MagicMock()to_make_provider()fixture. - test_rag_context_builder_contract.py: Added
scoring_policy=MagicMock()to_builder()fixture and inline construction site.
- src/platforms/ (12 files):
Dict/List/Optional/Tuple→dict/list/| None/tuplein all AI provider clients, exchange wrappers, and API clients. - src/trading/ (12 files): Full modernization of trading layer — brain, strategy, memory, exit monitor, position management, statistics, vector memory.
- src/managers/ (5 files): Model, persistence, provider orchestrator, types, risk manager. Added
from __future__ import annotationswhere forward refs with|needed. - src/notifiers/ (5 files): Base, console, Discord, file handler, and components.
- src/parsing/ (1 file): Unified parser.
- src/analyzer/ (19 files): Analysis engine, context, result processor, data fetcher, formatters, pattern engine, prompt builder, template manager, context builder, technical calculator. Added
from __future__ import annotationsfor forward ref support. - src/dashboard/ (6 files): State, routers (brain, monitor, performance, visuals, websocket).
- src/factories/ (2 files): Position and provider factories.
- src/indicators/ (4 files): Base indicators, technical indicators, support/resistance, volatility.
- src/rag/ (15 files): Article processor, category processor, collision resolver, context builder, file handler, index manager, market components, news manager, RAG engine, scoring policy, ticker manager. Added
from __future__ import annotationswhere needed. - src/contracts/ (1 file): Risk contract.
- All bare
Dict/List/Tupletype references (without subscript) converted todict/list/tuple.
- Entire codebase imports cleanly.
- 400 of 406 tests pass; 6 failures are pre-existing (confirmed via git stash).
- No
getattr()/hasattr()/setattr()in application code. - No Pydantic v1 patterns.
- No unused imports.
- Old-style typing (
Optional[X],Dict[K,V],List[X],Tuple[X], bareDict/List/Tuple) eliminated from all source files. from __future__ import annotationsadded to 5 files where forward references required it.
- 0
getattr()/hasattr()/setattr()in application code. - 400 of 406 tests pass; 6 failures are pre-existing.
- No Pydantic v1 patterns found.
- No unused imports.
- 33 files modified across all 4 phases, 0 regressions.
- unified_parser.py: Removed 2 defensive
isinstance(data, dict)guards in_normalize_numeric_fields()and_attach_response_validation(). Both functions are typed asdict[str, Any]— the isinstance checks were redundant with the type contract and silently masked type errors instead of failing fast.
- 400 of 406 tests pass; 6 failures are pre-existing.
- No regressions from isinstance removal.
- All 88 remaining isinstance calls in the codebase are legitimate: type-narrowing on
Any, polymorphic Union dispatch, exception classification, or untrusted-data validation.
- Added bounded timeout budgets for the market-knowledge refresh path so trading checks continue to analysis even when RSS fetch or article enrichment stalls.
- Added new
[rag]configuration keys in both config files:rag_update_timeout_seconds,news_fetch_total_timeout_seconds, andnews_enrichment_timeout_seconds. - Increased default
news_crawl_timeoutto 120s and kept it fully configurable. src/app.pynow wraps market-knowledge refresh with timeout handling and explicit fallback logs, preventing pre-analysis stalls.src/rag/news_ingestion/rss_provider.pynow applies outer timeouts to RSS fetch and enrichment stages, logs stage durations, and skips stalled enrichment without blocking execution.src/rag/news_ingestion/crawl4ai_enricher.pynow applies an explicit batch timeout around Crawl4AI runs and falls back to aiohttp with clear warning telemetry.src/rag/news_ingestion/schema_mapper.pynow removes high-confidence Decrypt-style market ticker prefixes before article bodies reach prompts or Discord notifications.src/notifiers/notifier.pynow retries transient Discord 5xx send failures (including 503 no healthy upstream) with bounded backoff for text, embed, and chart sends.
- test_discord_notifier_rate_limit.py (+40 new): Transient Discord 5xx retry behavior, retry backoff logic, non-transient failure handling.
- test_news_ingestion.py (+48 new): RSS fetch timeout, enrichment timeout skip, non-blocking execution paths.
- test_rss_provider_contract.py (+33 new): RSS provider contract coverage for fetch-stage timeout and enrichment-timeout skip behavior, stage duration logging.
- All 56+ tests pass with timeout and retry integration.
- Non-blocking execution confirmed: trading analysis proceeds even when RSS/enrichment stalls.
- Discord retry backoff working correctly for transient 5xx failures.
- Added a model-facing decision reasoning protocol and decision gate for regime classification, conflict resolution, HOLD discipline, UPDATE/CLOSE gating, and explicit invalidation checks.
- Added backend prompt metadata and dashboard metadata fields so prompt behavior can be attributed by prompt version, response-contract version, and prompt variant without injecting version text into the LLM prompt.
- Added non-blocking prompt preflight linting for critical response-format, analysis-step, analysis-time, JSON-example, token-count, and untrusted-context guardrails.
- Added Pydantic-based validation metadata for trading analysis responses while preserving the existing JSON parser and fallback behavior.
- src/parsing/unified_parser.py: Extended with response validation schema, decision gate logic, and error recovery paths.
- src/platforms/ai_providers/response_models.py: Added prompt metadata fields (version, variant, contract_version) and comprehensive validation models.
- test_prompt_linting.py (+65 new): Preflight linting coverage for response format, analysis steps, JSON examples, token counts, and untrusted-context detection.
- test_response_validation.py (+62 new): Pydantic validation metadata, decision reasoning protocol, conflict resolution gate, HOLD/UPDATE/CLOSE gating logic.
- test_template_manager.py (+24): Metadata field integration and template rendering with observability features.
- All 440+ line additions validated; zero regressions in response parsing.
- Preflight linting successfully detects common response-format violations before LLM execution.
- Updated
README.mdtop-level status messaging to remove outdated branch/news notes and clearly state demo-account/paper-trading scope, with no real exchange execution implemented in the public branch. - Added a compact
Latest Changes (May 2026)section inREADME.mdto make recent behavior updates easier to discover from GitHub and LLM retrieval workflows. - Refreshed
README.mdfeature and configuration guidance to reflect timeframe-aware memory windows, semantic-rule evolution, and current risk-management guardrails (max_position_sizeand fallback sizing tiers). - Rewrote
README.mddisclaimer language to emphasize not-financial-advice boundaries, user responsibility for local regulatory compliance, and warranty/liability consistency withLICENSE.md. - Expanded
CONTRIBUTING.mdwith local setup, testing expectations, changelog/documentation update requirements, and repository convention references. - Added a documentation navigation hub for faster contributor and LLM orientation.
- Refreshed documentation-plan metadata and completion notes to include May 6-7 updates and discoverability changes.
- Added GitHub workflow scaffolding with
.github/pull_request_template.mdand issue templates under.github/ISSUE_TEMPLATE/.
- Trading prompts now provide a parser-safe JSON example without pseudo-values, inline comments, or placeholder ranges, reducing invalid AI response risk for compact decision output.
- Response-format guidance now maps analysis steps to the existing five compact narrative lines, uses chart validation instructions only when chart analysis is available, and clarifies BUY/SELL, HOLD, UPDATE, and CLOSE JSON field semantics for open-position and no-position states.
- Confidence guidance now defers BUY/SELL entry thresholds to the dynamic response template and allows high-confidence HOLD decisions when staying out or maintaining a position is strongly justified.
- RAG/news/custom prompt snippets are now explicitly wrapped as untrusted market evidence so embedded article text cannot override system instructions, response format, risk rules, or trading policy.
VectorMemoryServicenow derives recency-decay defaults from the active timeframe at startup. For4h, this yields a 14-day half-life and a 56-day hard relevance window; lower timeframes use shorter windows, and higher timeframes use longer windows (capped).TradingBrainServicenow derives its closed-trade reflection scan cadence from the active timeframe: lower/noisier timeframes wait for more closed trades,4hkeeps the existing 5-trade baseline, and daily/weekly timeframes scan sooner while preserving semantic-rule sample gates.retrieve_similar_experiencesnow over-fetches vector candidates before ranking, applies a hard age cutoff for prompt relevance, and then hybrid-ranks fresh candidates by similarity and recency. Older entries remain stored but are no longer used as fallback filler when fresh candidates are insufficient.- Vector prompt context headers now include the active relevance window (
active window: last N days) so the model can reason with explicit memory freshness constraints. - System prompts now include a new
Trading Style & Horizonsection that adapts guidance to the active timeframe (scalping, intraday swing, swing, or position context), including expected hold horizon, noise tolerance, and news relevance window.
- Removed redundant
hasattr(),getattr(), andisinstance()checks from typed production paths, including config access, dashboard brain status/memory handling, prompt snapshot formatting, RAG retrieval, exit monitoring, retry logging, and AI provider response conversion. - Tightened internal contracts so services now use direct attribute and method access for known collaborators such as config objects, strategy exit checks, logger-bearing instances, semantic-rule memory, and canonical article/analysis payloads.
- Config loader now normalizes admin IDs, dashboard CORS origins, and RAG news sources at load time so downstream services receive concrete lists instead of re-checking input shapes.
- Removed verified unused internal code, including stale trading statistics dataclasses, token request tracking state, obsolete dashboard state broadcast helpers, an obsolete CCXT multi-price fallback, a dead CoinGecko coin-data fetcher, unused provider metadata, and unused helper methods/constants.
- Fixed dashboard countdown datetime arithmetic and cache eviction typing surfaced during cleanup validation.
- Semantic-rule refresh now checks all stored semantic rules for legacy unknown exit profiles and retires both stale loss-rule prefixes when a refreshed loss pattern changes between anti-pattern and corrective classification.
- Dashboard brain helpers now ignore malformed non-object JSON snapshots instead of relying on broad exception handling when building market context, brain status, memory, or current-position fallback price data.
src/trading/brain.pynow fills missing semantic-rule SL/TP execution metadata from the configured exit profile before grouping trades, storing new rules, or rendering prompt context. This prevents legacy closed trades from producingSL unknown/unknown | TP unknown/unknownwhen the bot has configured hard/soft exit settings.src/trading/vector_memory_rules.pynow supports targeted semantic-rule deactivation so refreshed resolved-profile rules can retire only their matching stale unknown-profile predecessors.start.pynow injects config-derived exit execution defaults into the trading brain and triggers a one-shot refresh when active semantic rules still contain unknown exit profiles.src/dashboard/routers/brain.pynow exposes dominant SL/TP intervals and rewrites legacy unknown exit-profile text for the Semantic Rules dashboard response.
- LLM
position_sizeparsing now treats explicit percent strings correctly, including values below 1% such as0.5%. - RiskManager position-size fallbacks for LOW/MEDIUM/HIGH confidence are now configurable under
[risk_management]and are used only when the AI omits or returns an invalidposition_size. - Brain and prompt defaults now keep
max_position_sizeas a hard cap without nudging normal entries up to the cap as a minimum.
- Discord and console performance summaries now calculate
Total P&L (%)from realized quote P&L divided by configured demo quote capital, matching persisted trading statistics. Previously the notifier summed per-trade percentages, so variable position sizes could show a positive total percent while quote P&L was negative. - Trading memory context now uses the same capital-based total P&L percentage when configured, while preserving average per-trade percentage separately.
src/analyzer/prompts/template_manager.py—## PREVIOUS ANALYSIS CONTEXTsystem-prompt section now includes a compact structured snapshot extracted from the previous AI response JSON block. The snapshot surfaces prior signal, confidence, entry/SL/TP/R/R/position size, trend direction and strength, confluence factor scores, and up to two key support/resistance levels alongside the existing narrative reasoning. Falls back to narrative-only when the JSON block is absent or malformed.src/analyzer/prompts/template_manager.py— A JSON-only previous response (no narrative text) now correctly produces a## PREVIOUS ANALYSIS CONTEXTsection; previously it was silently skipped.src/analyzer/prompts/template_manager.py—"reasoning"field instruction in the response template now asks for 3-4 sentences covering decision thesis, market regime, key invalidation trigger, and next watch condition, improving data quality for vector-memory similarity and subsequent analysis cycles.src/trading/trading_strategy.pynow uses the shared indicator classifiers when converting analysis results into entry market conditions, so realtechnical_datakeys such asatr_percent,macd_line/macd_signal,obv_slope, and Bollinger Band levels are preserved for trading-brain similarity storage.src/trading/data_models.py,src/factories/position_factory.py, andsrc/managers/persistence_manager.pynow persistorder_book_bias_at_entry, allowing stop-loss/take-profit exits to reconstruct the same order-book context used by vector similarity queries.
src/analyzer/prompts/template_manager.pynow handles lightweight config objects safely when building the response template. IfMAX_POSITION_SIZEis missing or invalid, it falls back to0.10instead of raisingAttributeError.src/rag/news_ingestion/rss_primitives.pynow accepts short but valid content fromarticle/article-content/main selectors, avoiding fallback parser output that could include unrelated sidebar text.
- Prompt formula corrected: The AI was instructed to use
position_size = confidence / 100, turning a 50% confidence into a 50% capital allocation. Formula is now(confidence / 100) × max_position_size(default 0.10), so confidence 75 → 0.075 (7.5% of capital). - Hard cap added in
RiskManager:calculate_entry_parametersnow clamps any AI-providedposition_sizetoconfig.MAX_POSITION_SIZE. A warning is logged when clamping occurs. min_pos_sizefloor corrected: The brain-learned floor for position sizing now defaults to0.02(was0.10) and is capped atmax_position_sizeto prevent floor > cap.- New config property
MAX_POSITION_SIZE: Added tosrc/config/loader.py, reading[risk_management] max_position_sizefromconfig.iniwith a default of0.10. config.ini/config.ini.example: Addedmax_position_size = 0.10under[risk_management].
- Restored dashboard Confidence KPI updates in
src/dashboard/routers/brain.pyby safely parsinganalysis.confidencefrom JSON blocks inresponse.text_analysiseven whentechnical_datais present. - This fixes the regression introduced after the Apr 30 confidence-path fix, where confidence fell back to
--when LLM output used JSON-only confidence (for example"confidence": 75) instead of aConfidence: 75%text line. - Added/updated coverage in
tests/test_dashboard_brain_router.pyto ensure confidence is extracted from both regex fallback text and JSON analysis payloads when indicator fields are present.
- Updated
src/trading/exit_monitor.pyso when both hard stop-loss and hard take-profit checks are due in the same tick, the monitor performs a single combined strategy check instead of two separate checks. - This prevents duplicate
Saved positionwrites/logs for unchanged open positions while preserving the same SL-first/TP-second evaluation semantics and timestamp persistence.
- Upgraded
aiohttpfrom3.13.3to3.13.4(CVE-2026-34513–34520, CVE-2026-22815 — 10 CVEs fixed). - Upgraded
cryptographyto≥46.0.7(CVE-2026-26007, CVE-2026-34073, CVE-2026-39892). - Upgraded
lxmlto≥6.1.0(CVE-2026-41066). - Upgraded
orjsonto≥3.11.6(CVE-2025-67221). - Upgraded
protobufto≥6.33.5(CVE-2026-0994). - Upgraded
pyasn1to≥0.6.3(CVE-2026-23490, CVE-2026-30922). - Upgraded
pygmentsto≥2.20.0(CVE-2026-4539). - Upgraded
pytestto≥9.0.3(CVE-2025-71176) — dev dependency. - Upgraded
python-dotenvto≥1.2.2(CVE-2026-28684). - Upgraded
requeststo≥2.33.0(CVE-2026-25645). - Upgraded
transformersto≥4.53.0(CVE-2025-3777, CVE-2025-3933, CVE-2025-5197, CVE-2025-6051, CVE-2025-6638, CVE-2025-6921). - Remaining unfixed:
pip==26.0.1(CVE-2026-3219) — no patched version published by PyPA yet.
start.pynow reads optionalHF_TOKENfromkeys.envand exports it to process environment (HF_TOKEN/HUGGINGFACE_HUB_TOKEN) beforeSentenceTransformerinitialization. This removes repeated unauthenticated Hugging Face Hub warnings when a token is configured and enables higher rate limits.keys.env.examplenow documents optionalHF_TOKENsetup.
src/trading/brain.py—_trigger_reflection()now evaluates all trades matching a pattern (wins and losses) via a shared_compute_group_metrics()helper. The win gate was lowered from 10 to 5 and rule IDs are now deterministic (rule_best_{pattern_key}) to prevent duplicate rules across repeated reflections. Storedbest_practicemetadata now includeswins,losses,win_rate,loss_rate,avg_pnl_pct,profit_factor,expectancy_pct,avg_mae_pct, andavg_mfe_pct. Rules are only stored when win rate is ≥ 60%.src/trading/brain.py—_trigger_loss_reflection()fully overhauled: loss gate lowered from 5 to 3, occurrence gate from 3 to 2. Uses_compute_group_metrics,_derive_failure_reason, and_derive_recommended_adjustment. Storesrule_typeof eitheranti_pattern(loss rate ≥ 60%) orcorrective(mixed). Deterministic IDs prevent duplicate rules.src/trading/brain.py— Added_trigger_ai_mistake_reflection()so repeated HIGH-confidence failures, sideways/choppy failures, and reasoning/premise mismatches produceai_mistakesemantic rules. These rules storemistake_type,entry_confidence,failed_assumption,failure_reason,recommended_adjustment, and win/loss/P&L metrics.src/trading/brain.py— Reflection keys now include hard/soft SL/TP execution profile. Stop-like close reasons such ashard_stop,hard_stop_loss,soft_stop_loss, andstop_loss_hitare normalized to the stop-loss diagnostic bucket while preserving the exact dominant exit profile in metadata.src/trading/brain.py—get_context()now renders rule type tags ([⚠️ AVOID],[⚡ IMPROVE],[🧠 AI MISTAKE]) and a recommended adjustment line for each learned rule. Apply Insights prompt now explicitly instructs the LLM to balance wins/losses, compare current reasoning to failed AI assumptions, and account for hard/soft SL/TP execution settings.src/trading/vector_memory_rules.py—get_anti_patterns_for_prompt()now fetchescorrectiveandai_mistakerules in addition toanti_patternrules and appends→ Why:/→ Fix:lines when diagnostic metadata is present.src/dashboard/routers/brain.py—get_active_rulesendpoint now maps all new metadata fields:rule_type,loss_rate,wins,losses,avg_pnl_pct,profit_factor,expectancy_pct,failure_reason,recommended_adjustment,mistake_type,entry_confidence,failed_assumption,dominant_close_reason,dominant_exit_profile,dominant_stop_loss_type, anddominant_take_profit_type.src/dashboard/routers/brain.pyandsrc/utils/indicator_classifier.py— Dashboard brain status and exit-execution context building now tolerate lightweight config objects by falling back tounknown/timeframe defaults when optional SL/TP execution attributes are absent.src/dashboard/static/modules/vector_panel.js—renderSemanticRules()updated: empty-state text no longer references "wins only"; rule cards now show a color-coded type badge (Best Practice / Avoid / Corrective / AI Mistake), wins/losses split, avg P&L, profit factor, exit profile, mistake type, failure reason, and an optional recommended adjustment line.src/trading/brain.py,src/trading/vector_memory.py, andsrc/trading/vector_memory_context.py— Brain reflection now runs every 5 closed trades instead of 10, and recency weighting for similar experiences now uses a 30-day half-life instead of 90 days so fresh market behavior affects prompts and semantic-rule synthesis faster.
src/trading/brain.py— New private helpers compute combined win/loss statistics, normalize stop-like close reasons, preserve hard/soft exit profiles, detect sideways AI overconfidence, derive failed AI assumptions from stored reasoning, and map those diagnoses to concrete LLM-actionable instructions. Shared metadata and loss-diagnostic helpers keep reflection rules DRY across best-practice, loss, and AI-mistake paths.
- Updated workspace settings in
.vscode/settings.jsonto disablepython.terminal.activateEnvironmentandpython.terminal.activateEnvInCurrentTerminal, and setpython-envs.terminal.autoActivationTypetocommand. This avoids Python Envs shell-startup profile injection failures (EPERMduringmkdir) observed on some Windows user-profile paths with non-ASCII characters, while keeping interpreter selection pinned to./.venv/Scripts/python.exe.
Primary commits: 926056e, 349d49a, d6a72cc, 551f67a, 1e244da, be5e190
- Replaced the old legacy-provider-driven news flow with a full RSS ingestion stack under
src/rag/news_ingestion/, includingrss_provider.py,rss_primitives.py,schema_mapper.py, and optional Crawl4AI enrichment viacrawl4ai_enricher.py. - Added
src/rag/scoring_policy.py,src/rag/news_repository.py, andsrc/rag/local_taxonomy.pyto support article scoring, storage, and local category handling without legacy provider category dependencies. - Started tracking
data/categories.jsonin Git as the local category/taxonomy snapshot used by the new RSS-driven news flow. - Added
src/platforms/ccxt_market_api.pyto formalize exchange market access outside the removed legacy market path. - Added
src/trading/exit_monitor.pyandsrc/trading/position_status_monitor.pyso stop-loss and take-profit execution can be checked on bot-side intervals instead of waiting only for candle-close logic. - Added two debugging scripts,
scripts/fetch_free_news_preview.pyandscripts/compare_news_body_quality.py, to inspect raw RSS ingestion and enrichment quality. - Added broad contract coverage for the new pipeline, including tests for news ingestion, RSS provider behavior, RAG retrieval/scoring contracts, exit monitoring, notifier rate limits, and CCXT migration.
- Reworked the configuration contract for news ingestion and exit handling.
config/config.ini.examplegained RSS source whitelisting, per-source feed URLs, page-enrichment controls, density/co-occurrence scoring knobs, lower-timeframe guidance, and the new[risk_management]hard-exit interval settings. Existing localconfig/config.inifiles need the same keys added manually becauseconfig/config.iniis intentionally ignored. - Removed the obsolete legacy-news API key entry from
keys.env.exampleto match the news migration away from the retired provider path. - Narrowed the
data/ignore rule in.gitignoreso the repo now keepsdata/categories.jsonunder version control while still ignoring the rest of the local runtime data directory. - Updated the bot runtime in
src/app.py,start.py,src/config/loader.py, andsrc/config/protocol.pyto wire the new RSS/news services, low-timeframe scheduling, exit-monitor settings, and richer config contracts. - Extended
src/dashboard/routers/brain.pyso dashboard state is derived from parsed analysis JSON and richer live-trading context instead of fragile regex-only extraction. The Apr 30 diff also shows position SL/TP distance fields being carried through the API more explicitly. - Reworked
src/rag/news_manager.pyandsrc/rag/context_builder.pyso RAG assembly now pulls from the RSS repository, local taxonomy, and scoring policy instead of the previous legacy-provider-oriented path. - Enhanced notifier output in
src/notifiers/base_notifier.py,src/notifiers/console_notifier.py, andsrc/notifiers/notifier.pyso trade alerts can include chart images and last-trade context. - Broadened
src/utils/indicator_classifier.pyandsrc/utils/timeframe_validator.pyto support exit-execution context, lower timeframes, and more explicit runtime scheduling rules.
- Landed a major O(N) optimization wave across indicator code. The release touched momentum, stochastic, moving-average crossover, support/resistance, and classifier-related paths, while the release notes and file diffs align on sliding-window rewrites for RSI, MACD, CCI, VHF, MAD, MFI, Z-score, Donchian, Ichimoku, Fibonacci Bollinger Bands, Vortex, Choppiness, and rolling volume filters.
- Tightened market data and persistence code around
src/analyzer/analysis_engine.py,src/analyzer/data_fetcher.py,src/analyzer/market_data_collector.py, andsrc/managers/persistence_manager.pyso the new ingestion and exit-monitor flows fit into the existing analysis loop.
- Fixed a critical path traversal issue in
src/rag/file_handler.pyand shipped a cluster of front-end hardening changes across dashboard modules for DOM XSS, mutation-XSS, clickjacking, and template interpolation bugs. - Fixed the dashboard confidence KPI path by moving the brain router toward parsed JSON extraction rather than depending on a
Confidence: XX%regex shape that no longer matched the prompt contract. - Fixed position sizing for values greater than 1% and hardened vector-threshold learning and reflection-key parsing in trading logic.
- Deleted legacy provider categories/data/market clients plus
src/rag/category_fetcher.pyandsrc/rag/news_category_analyzer.pyin the main release. - Deleted the remaining legacy provider news client and package stub in follow-up commit
1e244da, completing the migration away from retired-provider-backed news. - Deleted the public
data_template/tree inbe5e190after it became clear that the directory no longer matched the private mainline.
- The Apr 30 release was published in two steps: the main feature sync landed first, then same-day cleanup commits removed merge-conflict markers from
README.md, source files, andconfig/config.ini.example, and finished deleting leftover legacy-provider artifacts anddata_template/artifacts. This section describes the final cleaned-up public state.
Primary commit: 554a507 (Dependabot merge of 8319f44)
- Bumped Pillow from
12.1.1to12.2.0on the public branch. This was later carried forward into the Apr 30 release notes as the image-processing/security maintenance update.
Primary commit: 80389c1
- Added
tests/test_dashboard_server_cache.pyand expanded dashboard brain router coverage to validate new cache and state behavior.
- Implemented endpoint-aware dashboard caching with ETag/header strategy in
src/dashboard/server.py. - Updated dashboard client/runtime flow in
src/dashboard/static/main.jsandsrc/dashboard/routers/brain.pyto align vector queries and state handling with richer trading context. - Added fallback recomputation for SL/TP distance percentages in dashboard position output when persisted values are zero or missing.
Primary commit: 3493598
- Split dashboard styling into modular CSS files under
src/dashboard/static/css/. - Added
src/trading/vector_memory_analytics.py,src/trading/vector_memory_context.py, andsrc/trading/vector_memory_rules.py. - Added
src/utils/indicator_classifier.pyand new focused tests for context builder, dashboard routes, template manager, indicator classifier, and vector memory.
- Reworked dashboard layout and panel modules in
index.htmlandmain.js. - Updated analyzer, formatter, and indicator modules across momentum, sentiment, statistical, trend, volatility, support/resistance, and volume packages.
- Refined RAG and market-data processing paths and aligned dashboard/trading context behavior with vector-memory logic.
- Removed the old monolithic
src/dashboard/static/style.css. - Removed many internal diagnostic scripts and broad internal verification tests from the public release snapshot.
Primary commits: f03304b, 8621585, 5ba8169
- Simplified the legacy news-provider stack by collapsing the earlier multi-file
news_componentsstructure into a single provider news client paired with a leanersrc/rag/news_manager.py. - Expanded dashboard behavior again in
src/dashboard/routers/brain.py,monitor.py, andperformance.py, while also improving logging and monitor-route behavior. - Updated technical-calculation and risk-manager behavior alongside the dashboard and news refactor.
- Reworked public-facing documentation and licensing so the Mar 4 release shipped with a cleaned-up README structure and MIT-oriented release files.
- Added
tests/benchmark_monitor_news.pyduring the refactor phase to benchmark news monitoring before the public release tree was trimmed back.
- Removed the older provider news API module and legacy
news_components/modules after the refactor consolidated news fetching into a single client. - Removed additional dashboard, RAG, start-up, and test code in the public release commit to produce a smaller public release snapshot.
- Removed the remaining Polyform references from public documentation in the follow-up README cleanup commit.
Primary commit: 2f1a6ad
- Improved dashboard server binding/runtime handling and startup orchestration in
start.py. - Updated market/platform integrations around Alternative.me, CoinGecko, and legacy-provider API handling.
- Extended configuration behavior and associated test coverage (including dashboard config/cors paths).
Primary commit: d89a1f6
- Renamed
src/trading/dataclasses.pytosrc/trading/data_models.pyand expanded trade/position snapshots for richer brain and vector-memory context. - Strengthened AI provider base clients and retry/error-classification behavior across provider adapters.
- Added additional optimized statistical-indicator work (including kurtosis/skewness paths) with related regression coverage.
Primary commit: 576ddf8
- Improved dashboard routing/state behavior and refined server/static module implementations.
- Continued O(N)-oriented indicator and analyzer optimization pass.
- Expanded validation and security-related test coverage, including websocket origin and dashboard route checks.
Primary commits: a6e6af4, 9195a34
- Added
.pylintrc, broad regression/integration test expansion, and refreshed dashboard image assets. - Added a
data_template/snapshot for the public release packaging at that time.
- Overhauled dashboard UI/UX into a richer multi-panel surface with improved accessibility and interaction behavior.
- Reworked analyzer/trading/runtime layers for non-blocking I/O paths, stronger context handling, and improved orchestration.
- Applied multiple indicator/runtime correctness and performance improvements across trend, statistical, and momentum paths.
- Hardened dashboard security paths (including XSS/DoS-related fixes and websocket safeguards).
- Fixed a duplicate live dashboard link in README (
9195a34).
- Removed older agent/workflow artifacts such as
AGENTS.md,CONTRIBUTING.md, and obsolete Jules prompt files from the release snapshot.
Primary commits: a60020d, 04ff96d, a2ac568
- Moved runtime wiring toward a composition-root architecture in
start.pyand tightened dependency boundaries across analyzer, RAG, and trading services. - Added
PositionFactoryandDataFetcherFactory, improved graceful shutdown and position lifecycle handling, and cleaned imports/readability across touched modules. - Improved technical-analysis formatting, dashboard accessibility (aria labels and focus indicators),
UnifiedParserbehavior, and LM Studio model caching.
Primary commit: 59b6b71
- Added dashboard full-stack caching (HTTP cache headers plus RAM state cache) and refactored the brain router for high-traffic endpoint efficiency.
- Added cache verification tooling for headers and dashboard state TTL behavior.
Primary commits: bab3f48, df589da, f18e98d, 967b71a, 5ce1f67, 81a9c01, 77f935a, 5276279, ae2f983
- Delivered a broad analyzer/prompt/chart quality pass: pattern deduplication, markdown/prompt cleanup, chart visibility/tooltips, and indicator-tracking improvements.
- Added performance-focused refactors in market metrics and statistical indicators (including linear regression and O(N) optimizations).
Primary commit: ecd3eab
- Introduced the first usable dashboard layer with brain/performance monitoring views, dashboard state, and core UI modules.
Primary commit: f877508
- Added an initial integrated web dashboard build (UI, styling, and backend server wiring).
Primary commits: 6256e60 plus merged PR batch (500e7e3, 151b710, 7a0547e, f63d742, 9264bb9, 08f9fa6, de1f3a0)
- Added comprehensive trade-lifecycle regression coverage and merged a broad optimization/fix batch across indicators, async testing, and vector-memory integration paths.
Primary commits: 593c61b, c8ecc6f, 65d0bda, 1cb788d plus merged PR batch (80671e9, 61a05d4, cdb72b0)
- Added DefiLlama fundamentals integration and expanded market-overview/RAG market-data building.
- Merged security/accessibility/performance PRs and removed outdated AI agent guideline docs.
Primary commits: fe454f3, b6374e8, ce36abb, f9797fe plus merges (b1c1920, 6c22ccc)
- Expanded dashboard capabilities (statistics/news/positions panels), added dashboard security hardening and Cloudflare Tunnel support, and refreshed dependencies.
Primary commits: 2858c28, 036954a, 81f5c64, 47c9dec plus merged PRs (71d83a6, fb26593, c64edfe)
- Unified AI provider responses with Pydantic models and reduced redundant indicator calculations.
- Expanded AI chart generation and dashboard visual-analysis support while merging security/performance/accessibility PRs.
Primary commits: d12bdfe, 9684675, c31d755, 4c034bc (plus related updates)
- Improved LONG-bias mitigation logic and upgraded security dependencies (aiohttp) with safer dashboard error handling.
- Enforced UTC consistency in temporal/trading operations and tightened provider compatibility.
Primary commits: f0bf950, 1d73168, 66450ce, 4532bdf, 09f868a (plus refactor/cleanup updates)
- Added provider orchestration, stronger typed analysis context, expanded provider test coverage, and major dashboard feature growth (including new panels and synapse-style views).
- Continued large refactor wave across retrieval, parsing, and prompt/brain paths.
Primary commits: 614f685, cf168d1, 8e6d1f8, e24a04c, bdaba75, a67b9fc, 17a9f93, a3b551e, ff97d8e, 1e578d1, c4dafeb, 9a26fcd
- Major refactor/bugfix sweep across brain context, provider SDK integration, and performance tuning.
Primary commit: 8feb100
- Applied a focused bugfix/refactor pass across in-flight analyzer and trading logic.
Primary commit: 1d0141a
- Added non-breaking dynamic threshold learning enhancements in trading brain/vector memory using optional metadata and sample-size safeguards.
Primary commits: a061786, a30c942, b7b6730
- Delivered bugfix/refactor updates and richer brain context extraction (weekend awareness, sentiment/order-book pressure, and serialization cleanup).
Primary commit: 0271f7f
- Applied dashboard bugfixes after early rollout.
Primary commit: f2062e7
- Added core position-management strategy logic and dashboard routes for brain and position panels.
Primary commits: 450bce6, 3871980, 3e9d0a8, 7f26be1, a5c9955, e94ce36
- Added vector-memory service foundations and integrated analysis-engine/config-loader improvements.
- Expanded real-time dashboard capabilities with websocket-driven monitoring and chart management endpoints.
Primary commits: 6e8b0d0, 6a69c17, 029db43, 538ffd7, 85c884d (plus related updates)
- Added single-instance protection and shutdown confirmation flow.
- Improved prompt-building with position context, strengthened statistics update ordering, and refined trading insights handling.
Primary commits: large foundation batch including dcb6244, 4844ff9, 5bb354a, 301527b and related trading/notifier refactors
- Added foundational trading modules for memory, persistence, statistics, strategy execution, and brain context.
- Added vector-memory integration and application composition-root wiring in
app.py/start.py. - Refactored notifier/formatting and logger internals while cleaning circular-import pressure.
Primary commits: 3f08d9f, cff20ce
- Enhanced trading behavior with dynamic parameters and improved data handling.
- Updated ignore rules for research-paper artifacts.
Primary commits: f9d4dcd, eb4b7ac, 0082b19, 354058e, 15c9695
- Continued large refactor passes and refreshed README execution/notifier architecture documentation.
Primary commits: 2665dad, aeebd23, 6cb02a4, e9244ac, d84c267 plus related docs/CI updates
- Switched configuration workflow to
config/config.ini.exampleand ignored localconfig/config.ini. - Added Google/AI chart-generation foundations, early analysis-engine wiring, trading brain dataclass work, and context-builder expansion.
Primary commits: broad infrastructure batch including 35c3a24, 45490e5, 72f4f71, dba5720, 0f9be19
- Added dependency-injected app initialization, notifier abstractions, technical indicator coverage, persistence/config defaults, and licensing/readme updates.
- Cleaned repository tracking for agent-related folders.
Primary commits: 5b14c43, 6e24348, 3cf41f7, 3d650fc, d701a80, 30a596b, 7946feb and related fixes/tests
- Added foundational RAG engine improvements, OpenRouter multimodal integration, CoinGecko and legacy-provider market feeds, and core bot orchestration/prompt modularization.
Primary commits: 969aaa9, 660b55e, 922b4b2, cdae3af, 4ce9b80
- Added trading-brain factor learning, RAG context/profiling utilities, provider-factory and exchange-manager restructuring, periodic Discord trade-status notifications, and v2 documentation updates.
Primary commits: ed2c5a7, 0feb6b6
- Fixed indicator crossover detection for historical context and refactored core analysis/strategy/logging infrastructure.
Primary commit: 05dad4c
- Added a mock AI provider path for offline testing and analysis flows.
Primary commit: c849ab7
- Added AI model management protocols and abstraction foundations.
Primary commits: 726676e, e61d869, ccf1207, 1e17af3
- Initial public project bootstrap: analyzer/RAG architecture, trading persistence foundations, and core bot functionality/error-handling scaffolding.