177 Commits

Author SHA1 Message Date
Celes Renata c85c0068a2 fix: clean up utcnow deprecation warnings, fix 12 failing tests, add CI/CD pipeline manifests
- Replace all datetime.utcnow() with datetime.now(tz=timezone.utc) across 8 files
- Fix 12 failing tests to match current implementation behavior
- Fix pytest_plugins in non-top-level conftest (moved to root conftest.py)
- Auto-fix 189 lint issues (import sorting, unused imports)
- Add CI/CD pipeline infrastructure (ARC, ArgoCD, Kargo manifests)
- Add values-beta.yaml and values-paper.yaml for staged deployments
- Update GitHub Actions workflow to use self-hosted-gremlin runners
- Add integration-test job to CI pipeline

Result: 1596 passed, 0 failed, 0 warnings
2026-04-18 03:59:28 +00:00
Celes Renata ee5fd30398 fix: backtest force-closes open positions at end + uses real market prices for exits 2026-04-18 00:03:51 +00:00
Celes Renata 82da8af02b fix: dedup recommendation queue at aggregation level — prevent duplicate ticker+window flooding 2026-04-17 22:11:59 +00:00
Celes Renata a6189fce6b fix: skip LLM thesis rewrite for informational/suppressed recs to prevent queue buildup 2026-04-17 19:29:41 +00:00
Celes Renata 7736554988 fix: recommendation worker now respects thesis-rewriter active=false toggle 2026-04-17 19:22:31 +00:00
Celes Renata d8f1b615c8 fix: add order status sync loop to broker adapter — pending orders now update to filled/cancelled 2026-04-17 17:38:10 +00:00
Celes Renata aa67523acd fix: ensure JSON output instruction in system prompt override + retry on ValueError 2026-04-17 17:03:58 +00:00
Celes Renata 523d3ea749 fix: catch ValueError in classification retry loop + add debug logging for raw output 2026-04-17 17:00:32 +00:00
Celes Renata f054e97b5b fix: event classifier unwraps single-element list from model output
Model sometimes returns [{...}] instead of {...}. Now unwraps
single-element lists before parsing the event fields.
2026-04-17 16:44:57 +00:00
Celes Renata 76ff7ae00a fix: ruff import sort order 2026-04-17 16:37:30 +00:00
Celes Renata 1394e6168b fix: event classifier now strips markdown fences and repairs JSON
_parse_classification_response receives raw model output (with thinking
tags, markdown fences, etc.) but was calling json.loads directly.
Now uses _strip_markdown_fences + _repair_json from the client module
before parsing, matching what _call_ollama does for extractions.
2026-04-17 16:35:13 +00:00
Celes Renata 759d868e3b fix: event classifier was blocked by extraction schema validation
_call_ollama validates against the document extraction schema, which
doesn't match event classification output. The event classifier was
checking 'if attempt.error is None' before trying its own parsing,
so it never got to parse the valid event JSON — 956 consecutive
failures.

Now tries _parse_classification_response whenever raw_output exists,
regardless of the extraction validation error.
2026-04-17 16:28:39 +00:00
Celes Renata 5efccb1e03 fix: deduplicate evidence refs in trend summaries
Backend: assemble_trend_with_evidence now deduplicates document IDs
via dict.fromkeys() (the rollup code already did this, but the base
assembly didn't — same doc could appear multiple times from different
intelligence extractions).

Frontend: Trends.tsx deduplicates via Set before rendering as a safety
net for existing data already stored with duplicates.
2026-04-17 07:25:32 +00:00
Celes Renata 419cf7558a fix: evidence articles missing on recommendations + Lucide title prop CI failure
- recommendation worker: filter out non-UUID document IDs (synthetic
  pattern:* IDs from competitive signals) before inserting into
  recommendation_evidence table — the uuid cast was failing and
  silently dropping all evidence rows
- wrap executemany in try/except so partial failures don't lose all evidence
- SqlExplorer: wrap Lucide icons in <span title=...> instead of passing
  title prop directly (not supported by lucide-react, broke CI build)
2026-04-17 07:10:21 +00:00
Celes Renata 913fe8b0b3 feat: override trade tab — manual order entry with auto-registration
Backend:
- OverrideOrderRequest/Response Pydantic models with ticker, quantity, price validators
- POST /api/trading/override/order endpoint (enqueue to Redis broker queue)
- auto_register_symbol() module for untracked ticker registration via Symbol Registry
- Unit tests (17) and property-based tests (3 x 100 examples)

Frontend:
- OverrideTradePanel component (order form + positions display)
- Override tab in TradingEngine page with URL search param navigation
- Override Trade button on Trading Controls page
- useSubmitOverrideOrder mutation hook
- MSW handler and 13 component/integration tests

Steering:
- Updated steering docs for Ubuntu dev machine with nvm/Node 24
2026-04-17 07:02:30 +00:00
Celes Renata cbe3fbe8b4 feat: enrich SQL explorer schema browser with PK/FK, row counts, search, collapsible tables 2026-04-17 06:22:04 +00:00
Celes Renata bbf7a6ee7b fix: sort imports in api/app.py to fix ruff lint 2026-04-17 06:19:03 +00:00
Celes Renata b149f70507 fix: operator approval workflow — add approval toggle, lockout CRUD, and PBT tests
- Add GET/PUT /api/admin/trading/approval-config endpoints
- Add POST/DELETE /api/admin/trading/lockouts endpoints
- Add useApprovalConfig, useUpdateApprovalConfig, useCreateLockout, useDeleteLockout hooks
- Add Paper Order Approval toggle card with confirmation dialog
- Add lockout creation form and delete button to Active Lockouts card
- Add MSW handlers for all new endpoints
- Add property-based tests for bug condition exploration and preservation
2026-04-17 06:14:46 +00:00
Celes Renata 3b7ded37cc fix: global event detail returns 'impacts' field to match frontend type
API was returning 'affected_companies' but frontend GlobalEventDetail
type expects 'impacts'. Renamed the response field.
2026-04-17 05:30:36 +00:00
Celes Renata 62769c9b7e fix: macro impacts API returns {exposure_profile, impacts} to match frontend type
API was returning a flat array but frontend expects CompanyMacroImpacts
wrapper with exposure_profile and impacts fields. Also queries the
exposure_profiles table for the company's active profile.
2026-04-17 05:26:08 +00:00
Celes Renata 7c23c044d7 feat: agent variants — migration, API, service integration, frontend, tests
- Migration 027: agent_variants table with single-active enforcement,
  variant_id column on agent_performance_log
- API: full CRUD, clone from agent/variant, activate/deactivate,
  per-variant performance metrics and history endpoints
- Services: extractor, event classifier, thesis rewriter all wired
  to AgentConfigResolver with variant override support
- Frontend: variant list, comparison view, create/edit/clone forms,
  activate/delete actions on Agents page
- Tests: API tests + 5 property-based tests (single-active invariant,
  clone preservation, config resolution, slug determinism, update idempotence)
- Spec files for agent-variants feature
2026-04-17 05:15:42 +00:00
Celes Renata 734bf001a7 feat: risk tier selector on Trading page + confidence filter on Recommendations
- Trading page: added conservative/moderate/aggressive selector that
  updates the trading engine config via PUT /api/trading/config
- Recommendations page: added risk tier dropdown that defaults to the
  engine's current tier and filters recs by the tier's min_confidence
- Backend: added min_confidence query param to GET /api/recommendations
- Risk tier thresholds: conservative ≥0.75, moderate ≥0.55, aggressive ≥0.40
2026-04-17 05:08:54 +00:00
Celes Renata 49e3955fab fix: add missing agent_config.py — was untracked, causing extractor crash in cluster 2026-04-17 04:41:58 +00:00
Celes Renata fd862da29e fix: remove broken capital controls, reset now queries broker for real balance
- Removed PUT /api/trading/capital (set capital) — only touched in-memory state
- Removed POST /api/trading/capital/adjust (add/withdraw) — same problem
- Reset endpoint now: liquidates Alpaca positions, cancels orders, clears DB,
  then queries Alpaca for real portfolio_value to set engine capital
- Frontend: replaced CapitalCard with simple ResetCard (one button)
- Removed useSetTradingCapital and useAdjustCapital hooks
2026-04-17 04:24:10 +00:00
Celes Renata 5fb59b379c feat: reset endpoint now liquidates Alpaca positions and cancels orders
- Added cancel_all_orders() and close_all_positions() to AlpacaBrokerAdapter
- Reset endpoint creates a temporary adapter to call Alpaca DELETE /v2/orders
  and DELETE /v2/positions before clearing DB and engine state
- Also clears positions table and processed_recommendation_ids on reset
- Broker reset is best-effort — DB/engine reset proceeds even if Alpaca fails
2026-04-17 04:03:31 +00:00
Celes Renata e21f162e48 fix: dampen agreement factor by sample size in trend confidence to prevent low-evidence inflation
Agreement of 1-2 signals was inflating confidence to paper-eligible
levels (0.575) even with low credibility sources. Added log2-based
dampener that scales agreement contribution by unique source count,
saturating at n=7. Single signals now cap at 0.39 confidence,
2 signals at 0.49 — both correctly below paper threshold (0.50).
2026-04-17 03:41:39 +00:00
Celes Renata 6179382d1e feat: wire all 3 agents to DB config resolver
- Recommendation worker now resolves thesis-rewriter config from DB
  and passes ollama_config to generate_recommendation. Thesis rewriting
  is now active when the thesis-rewriter agent exists in ai_agents.
  Refreshes config every 50 jobs.

- Event classifier now resolves its own config separately from the
  document extractor via 'event-classifier' slug. Uses a separate
  OllamaClient when the model differs from the extractor. Refreshes
  alongside the extractor every 100 jobs.

- Document extractor was already wired (existing code).

- Added 8 unit tests for AgentConfigResolver covering: DB resolution,
  variant override, not-found, DB errors, TTL caching, cache refresh,
  and invalidation.
2026-04-17 02:59:40 +00:00
Celes Renata c501ccea40 fix: default model to qwen3.5:9b + improve event classifier prompt
- Migration 026 and OllamaConfig now default to qwen3.5:9b instead of
  llama3.1:8b. Existing deployments keep their current model (qwen3.5:9b-fast)
  since the migration uses WHERE NOT EXISTS on slug.

- Event classifier system prompt expanded with macro-vs-company filtering:
  explicitly instructs the model to NOT classify single-company news
  (lawsuits, earnings, management changes, debt crises) as macro events.
  Sets severity=low and confidence<0.3 for company-specific articles.
  Reserves 'critical' severity for multi-country/global market events.
  Prevents over-tagging event_types by requiring direct description.

- Updated test_system_prompt_is_concise threshold to accommodate the
  expanded prompt (300 → 1000 chars).
2026-04-17 02:53:38 +00:00
Celes Renata 90614dd7bb feat: paper trading capital controls — add, withdraw, and full reset
Three distinct capital operations on the Trading Controls page:

- Set Capital: overwrites pool balances to a new amount (existing)
- Add/Withdraw: adjusts active pool by a delta without touching
  positions, orders, or history. Validates sufficient balance for
  withdrawals. Logged to reserve_pool_ledger as manual_adjustment.
- Reset Everything: nuclear option — deletes all positions, orders,
  trading decisions, stop levels, snapshots, backtests, notifications,
  and circuit breaker events, then resets capital fresh. Red button
  with double-confirmation dialog.

Backend: POST /api/trading/capital/adjust and POST /api/trading/reset
Frontend: CapitalCard rebuilt with three sections and confirmation UIs
2026-04-17 02:23:26 +00:00
Celes Renata 45752b9a29 feat: AI Agents management page with per-agent performance tracking
New Agents tab in the sidebar (Ops group) for viewing, editing, and
creating AI agent configurations:

Database (migration 026):
- ai_agents table: editable configs for each LLM agent (model, prompts,
  temperature, tokens, retries). source='system' for built-in,
  source='user' for custom. Seeds 3 system agents (Document Extractor,
  Event Classifier, Thesis Rewriter) using WHERE NOT EXISTS to never
  overwrite user edits across reinstalls.
- agent_performance_log table: per-invocation metrics (duration,
  confidence, retries, tokens, errors) linked to agent config.

API endpoints:
- GET/POST /api/agents — list and create agents
- GET/PUT/DELETE /api/agents/{id} — view, edit, delete (system agents
  can be edited but not deleted)
- GET /api/agents/{id}/performance — aggregated metrics (success rate,
  avg/p95 latency, confidence, token usage)
- GET /api/agents/{id}/performance/history — hourly time series

Frontend:
- AgentsPage with sidebar list + detail panel
- Agent detail: config display, system prompt viewer, performance
  dashboard with metrics cards and time-series chart
- Edit form: all config fields editable including system prompt,
  model, temperature, tokens, retries
- Create form: new user-defined agents with auto-slug generation
- System agents show blue badge, user agents show green badge
2026-04-17 01:24:35 +00:00
Celes Renata 2360c501e4 feat: intraday hourly price bars via Polygon range endpoint
- New 'intraday_bars' endpoint in PolygonMarketAdapter: fetches hourly
  bars for today using range_bars URL with timespan=hour, sort=asc
- Scheduler expands intraday_bars global source into per-ticker jobs
  for all active companies (every 15 minutes via polling_interval)
- Migration 025 inserts the intraday source with 900s cadence
- Frontend price matching uses closest-timestamp instead of date-string
  matching, with 2h tolerance for intraday and 36h for daily windows
- Bumped market price fetch limit to 200 for intraday granularity
2026-04-17 01:13:24 +00:00
Celes Renata c4206b3f4c feat: overlay stock price on trend charts with right Y axis
- New GET /api/market/prices/{ticker} endpoint serving OHLCV data from
  market_snapshots, deduped by bar_timestamp
- New useMarketPrices hook in frontend
- Trend chart now shows price (purple line) on a right Y axis ($)
  alongside trend metrics (%) on the left Y axis
- Custom tooltip formats price as dollars, metrics as percentages
- Price line uses connectNulls for days with missing bar data
2026-04-17 01:09:36 +00:00
Celes Renata 7c589353f8 fix: blank company charts + competitor GUIDs instead of tickers
Trend charts blank:
- trend_windows uses upsert (1 row per ticker/window), so charts had
  at most 1 data point. Added trend_history table (migration 024) that
  appends every snapshot. New /api/trends/history endpoint serves the
  time series. Frontend now uses useTrendHistory for charts and
  useTrends for the latest summary card.

Competitor GUIDs:
- list_competitors query returned raw company_b_id UUIDs without
  joining companies table. Added LEFT JOIN with CASE to resolve the
  other company's ticker and legal_name. Updated Pydantic model to
  include enriched fields. Frontend fallback changed from truncated
  UUID to ticker/legal_name/Unknown.
2026-04-17 00:42:55 +00:00
Celes Renata f2d8744a4f fix: backtest submission shows no results — 4 bugs fixed
- ID mismatch: API generated a throwaway UUID while BacktestReplay
  generated its own internally. Frontend polled with wrong ID and
  never found the DB row. Now pre-generate ID in endpoint and pass
  it to BacktestReplay.
- Field name: API returned 'backtest_id' but frontend read 'data.id'.
  Unified to 'id' everywhere.
- No polling: useBacktestResult fired once and never refreshed.
  Added refetchInterval that polls every 2s while status is running.
- Response shape: GET endpoint nested results under 'result' object
  but frontend expected flat fields. Flattened response to match
  BacktestResult type.
- Added running/failed/completed status indicators in BacktestPanel.
2026-04-17 00:31:17 +00:00
Celes Renata f11aa0a1ee fix: deduplicate recommendations and widen position sizing range
- Add dedup check in recommendation worker: skip generation when latest
  rec for same ticker+window has identical action/mode/confidence
- Widen position sizing range (1-10% portfolio, 0.3-2% max loss) and
  factor in trend strength + evidence count for differentiated sizing
- API returns only latest recommendation per ticker by default (DISTINCT ON)
  to eliminate duplicate rows in the frontend list view
2026-04-17 00:15:32 +00:00
Celes Renata 29f46d387c fix: 6 buy/sell logic bugs — sells check trading window, persist audit trail, dedup after position check, no duplicate buys, fix stop-level insert, profit-taking respects market hours 2026-04-17 00:07:50 +00:00
Celes Renata 1246b3868b fix: use current_price not avg_entry_price for invested calc — prevents margin-inflated numbers showing $0 available 2026-04-17 00:04:12 +00:00
Celes Renata f57167ce4d fix: only poll recommendations from last 2 hours (not 24h), persist snapshots during market hours for performance tab 2026-04-16 23:53:54 +00:00
Celes Renata 18eb150c75 fix: confidence formula now uses unique doc count + signal agreement instead of raw signal count — prevents 99.9% inflation 2026-04-16 23:48:05 +00:00
Celes Renata 1a5fb2e36a fix: recovery sweep touches updated_at after re-enqueue to prevent duplicate flooding every 5 min 2026-04-16 19:13:10 +00:00
Celes Renata 693d9e0d60 fix: reduce LLM timeouts — truncate docs to 8k/6k chars, cut num_predict 16k→4k, tighten prompts, trim anti-hallucination rules 2026-04-16 18:56:11 +00:00
Celes Renata 60cfb7618e fix: recovery sweep skips docs that already have global_events — prevents re-enqueue loop 2026-04-16 18:27:21 +00:00
Celes Renata 1043710b6d fix: track last_published_at per source to avoid re-fetching same articles — applies to both news_api and macro_news 2026-04-16 18:12:12 +00:00
Celes Renata 513310abba fix: stop tagging all macro_news articles as macro_event — default to article, let extractor reclassify. Also reduced fetch limit to 20 and cadence to 30min 2026-04-16 18:09:50 +00:00
Celes Renata f83577480f fix: alternate extractor between macro and extraction queues (1:2 ratio) to prevent starvation 2026-04-16 17:45:25 +00:00
Celes Renata 2440cddd37 feat: add comprehensive table retention cleanup to scheduler — 10 tables with per-table retention windows 2026-04-16 15:56:50 +00:00
Celes Renata 63287903d0 feat: wire up stop levels, circuit breaker daily loss, profit-taking, real portfolio/decisions/history endpoints 2026-04-16 15:52:46 +00:00
Celes Renata 1329df0bbf feat: sell execution, correlation matrix from market data, US market holiday awareness
- Sell path: looks up existing position, sells full quantity, returns proceeds to pool
- Correlation matrix: computed from 30-day market_snapshots on startup + every 5min
- Holidays: 10 major US market holidays for 2026 checked in trading window functions
2026-04-16 15:36:49 +00:00
Celes Renata 2e77cf32fd fix: critical — track capital properly: load invested positions on startup, deduct on act, sync every 5min 2026-04-16 15:29:28 +00:00
Celes Renata 9a8d36068a fix: convert Decimal to float in API responses instead of string — fixes positions page crash 2026-04-16 15:25:40 +00:00