Commit Graph

121 Commits

Author SHA1 Message Date
Elie Habib
d40dc246ae Improve Polymarket: tag-based event queries, clickable links
Switch from volume-only market fetching to tag-based event queries
for better relevance. Variant-aware tags (geopolitical vs tech).
Deduplicates across tag queries, falls back to top-volume markets
only when needed. Add clickable links to Polymarket event pages.
2026-01-29 15:19:31 +04:00
Elie Habib
8b58af0452 Remove unreliable Kuwait symbol (only 1 data point on Yahoo) 2026-01-27 18:14:14 +04:00
Elie Habib
d804dc7c85 Fix Middle East stock indices: add UAE DFM, fix Kuwait, use 1mo range
- Add DFMGI.AE for UAE (DFM General Index)
- Use range=1mo instead of 5d to handle Sun-Thu trading weeks
- Take last ~5 trading days from monthly data for weekly % change
- Remove broken Qatar symbol (^QSI returns no data)
2026-01-27 17:23:47 +04:00
Elie Habib
e28c3f7123 Remove broken Yahoo Finance symbols (AE, VN, NG, KE, CO, PK, BD, GR, RO)
Yahoo Finance doesn't carry indices for UAE, Vietnam, Nigeria, Kenya,
Colombia, Pakistan, Bangladesh, Greece, or Romania.
2026-01-27 17:20:19 +04:00
Elie Habib
67d06ebbf4 Add stock market index to country intel + pause renders during modal
- Stock index API endpoint (Yahoo Finance, Redis 1h cache, ~50 countries)
- Stock chip in modal: shows weekly % change with green/red styling
- Pause deck.gl renders while country modal is open (fixes flickering)
- Suppress signal modal clicks while country modal is visible
- Single stock fetch reused for both UI chip and AI brief context
2026-01-27 17:14:43 +04:00
Elie Habib
97f3d75249 Comprehensive country intel: geo-based military counts, richer context, expanded prompt
- Military signals now counted by geographic bounding box (lat/lon in country)
  instead of operator flag — matches what posture panel shows
- Add country aliases for headline matching (Israel → israeli, gaza, hamas, idf...)
- Feed convergence scores + regional alerts to AI context
- Expanded prompt: 5 sections, 300-400 words, military posture analysis,
  regional context, cross-signal correlation
- Bump max_tokens 500→900, cache version ci-v1→ci-v2
- Add 25+ country bounding boxes for geo-matching
2026-01-27 16:56:39 +04:00
Elie Habib
1292f0595f v2.1.0: Country click → AI intelligence brief
Click empty map area to detect country via Nominatim reverse geocoding,
highlight it with GeoJSON boundaries, and show an AI-generated intel
brief (Groq, Redis-cached 2h) with CII score, active signals, and
contextual news headlines.
2026-01-27 16:43:52 +04:00
Elie Habib
c3c2fd7341 Fix military detection false positives and code quality
- Remove CCA from MILITARY_PREFIXES (Air China airline, not military)
- Remove duplicate IAF entry from Middle East section
- Move AIRLINE_CODES to module level Set for O(1) lookup
- Remove duplicate entries (ELY, THY, SWR)
2026-01-27 08:33:38 +04:00
Elie Habib
2801453057 Add ADS-B Exchange military aircraft database
- 20,396 verified military hex IDs from adsbexchange.com
- Updated daily by ADS-B Exchange community
- O(1) lookup using Set
- Combines with callsign detection for comprehensive coverage
2026-01-27 08:21:20 +04:00
Elie Habib
a7126f3ad2 Simplify hex ranges to high-confidence military blocks
Focus on ranges where military/civilian separation is clear:
- US (AE/AF), UK, France, Germany, NATO, Russia, China, Australia, Japan

For other countries, rely on callsign detection since hex ranges
include commercial aircraft mixed with military.
2026-01-27 08:14:29 +04:00
Elie Habib
5719075866 Refine military hex ranges to exclude commercial
Previous ranges were too broad, catching commercial airlines.
Now using confirmed military-only blocks based on OSINT sources.
2026-01-27 08:11:53 +04:00
Elie Habib
8f667b26b1 Add ICAO hex range detection for military aircraft
Military aircraft have specific transponder ID ranges by country.
This matches how OpenSky UI identifies military aircraft.
Now checks both callsign patterns AND hex ranges.

Ranges added for: USA, UK, France, Germany, Italy, NATO, Israel,
Saudi, UAE, Qatar, Turkey, Russia, China, Iran, India, Pakistan,
Australia, Japan, South Korea
2026-01-27 08:09:23 +04:00
Elie Habib
aad378bc29 Fix military detection false positives
- Remove UAE from military prefixes (conflicts with Emirates airline)
- Use more specific UAEAF, BAHAF, OMAAF for Gulf military
- Expand airline exclusion list with major carriers worldwide
- This improves accuracy by removing commercial flight false positives
2026-01-27 08:06:37 +04:00
Elie Habib
f241adca64 Expand military callsign detection
- Add more US military prefixes (ARMY, NAVY, USAF, OPS, etc.)
- Add Middle East military prefixes (RSAF, UAE, EMIRI, etc.)
- Add NATO tactical callsigns (SWORD, LANCE, etc.)
- Add short tactical pattern (3 letters + 1-2 digits) with airline exclusion
- Exclude known airline codes (SVA, QTR, THY, etc.) from short patterns
2026-01-27 07:59:05 +04:00
Elie Habib
cd3369bf29 Fix isMilitaryCallsign - remove overly broad regex patterns
The patterns [A-Z]{2,3}\d{3,4} and [A-Z]{3,4}\d{2,4} were matching
commercial airlines like PGT5873, IAW9011, IZG3020. New pattern only
matches 4+ letter callsigns like DUKE01, VIPER12 which are typical
military tactical callsigns.
2026-01-27 07:52:25 +04:00
Elie Habib
175a34d5cc Fix Wingbits field mapping - use short field names (h, f, la, lo, ab, th, gs)
BUG FIX: Wingbits API returns short field names like 'h' for icao24,
'f' for flight, 'la' for latitude, etc. The previous code was looking
for long names like 'icao24', 'callsign', 'latitude' which don't exist
in the response, causing all flights to be filtered out.
2026-01-27 07:49:40 +04:00
Elie Habib
3f3bbd3e3d Add Wingbits as fallback flight data source when OpenSky fails
- Add /flights and /flights/batch endpoints to wingbits proxy
- Add fetchMilitaryFlightsFromWingbits() to theater-posture API
- Try OpenSky first, fallback to Wingbits on 429/failure
- Transform Wingbits data to match existing flight format
- Add 'source' field to response ('opensky' or 'wingbits')
2026-01-27 07:22:51 +04:00
Elie Habib
2082613c28 Improve theater posture caching and fix Times of Israel feed
- Switch Times of Israel from Railway to Vercel RSS proxy (already allowlisted)
- Increase stale cache TTL from 1 hour to 24 hours
- Add 7-day backup cache as last resort during prolonged outages
- Better error handling: try stale → backup → error
2026-01-27 07:09:33 +04:00
Elie Habib
31471b19af Fix aircraft type classification defaulting to fighter
- Change default from 'fighter' to 'unknown' for unrecognized callsigns
- Add 'unknown' count to aircraft breakdown
- Show bombers, transport, drones, and 'other' in summary
- Fixes misleading '179 fighters' when most were unclassified
2026-01-26 22:46:39 +04:00
Elie Habib
8cd9e4f149 Fix weighted average calculation in strategic risk score
Bug: divisor returned last weight (0.40) instead of sum (3.5)
Fix: compute weights array, sum explicitly, divide correctly
2026-01-26 15:05:49 +04:00
Elie Habib
d80e7a5db9 Fix ACLED API: update endpoint URL and add auth + baseline fallback
- ACLED changed API endpoint from api.acleddata.com to acleddata.com/api/
- Add Bearer token authentication via ACLED_ACCESS_TOKEN env var
- Add baseline scores fallback when ACLED is unavailable (no more 500s)
- Better error logging for auth failures
2026-01-26 14:38:28 +04:00
Elie Habib
9ed33b99ef Add stale cache fallback for risk-scores API when ACLED fails 2026-01-26 13:43:43 +04:00
Elie Habib
e9e838b455 Fix bugs found in code review: missing isStale, variable shadowing, stale timestamp 2026-01-26 13:23:03 +04:00
Elie Habib
1b4d9b9157 Fix wingbits API: add explicit routes for nested paths (Vercel catch-all limitation) 2026-01-26 13:18:51 +04:00
Elie Habib
9467f79b15 Use Railway relay for OpenSky to avoid rate limits 2026-01-26 13:14:58 +04:00
Elie Habib
bcd774c888 Improve theater posture resilience and UX
- Add stale cache fallback when OpenSky is rate-limited (1h TTL)
- Return cached data instead of 500 error when API fails
- Improve empty/error state messages with context
- Add retry buttons to no-data states
- Show stale data warning when using cached fallback
2026-01-26 13:09:24 +04:00
Elie Habib
76af54caa3 Add Yemen/Red Sea theater (Houthi/Bab el-Mandeb) 2026-01-26 13:01:08 +04:00
Elie Habib
7ccbbf2f19 Add Israel/Gaza theater, adjust E.MED bounds 2026-01-26 12:58:21 +04:00
Elie Habib
e83ea1a508 Add 3 more strategic theaters for better global coverage
- Korean Peninsula (covers Korean DMZ area)
- South China Sea (disputed waters)
- Eastern Mediterranean (Israel/Syria/Lebanon)

Bump cache key to v2 to invalidate old 4-theater cache.
2026-01-26 12:56:19 +04:00
Elie Habib
8565483826 Remove dead code: REAPER already handled by drone pattern 2026-01-26 12:53:11 +04:00
Elie Habib
7e9251a396 Fix critical bugs in theater posture feature
- Add missing byOperator to API response (was causing crash)
- Deep clone postures to prevent cached data mutation
- Add drone detection patterns (RQ/MQ/REAPER/PREDATOR)
- Separate drone from reconnaissance in callsign detection
2026-01-26 12:41:19 +04:00
Elie Habib
4e0e88d223 Unify theater posture: combine aircraft + naval vessels
- Add vessel fields to TheaterPostureSummary type (destroyers, frigates,
  carriers, submarines, patrol, auxiliaryVessels, totalVessels)
- Update API to return theater bounds for client-side vessel matching
- Panel fetches vessels client-side (AIS WebSocket) and merges with
  server-side aircraft data (OpenSky API)
- Display shows AIR and NAVAL sections when vessels detected
- Add posture-section-label CSS for section headers
2026-01-26 12:20:44 +04:00
Elie Habib
d0eabdf3c8 Add timeout to OpenSky fetch in theater-posture API 2026-01-26 11:08:58 +04:00
Elie Habib
4247ba70b8 Add server-side caching for theater postures
- Create /api/theater-posture.js endpoint that fetches military flights
  from OpenSky, calculates theater postures, and caches in Upstash Redis
- Add cached-theater-posture.ts client service with deduplication
- Update StrategicPosturePanel to fetch from cached endpoint independently
- Update App.ts to use cached postures for critical alert banner

Benefits: Theater posture calculation shared across all users via Redis
cache (5-min TTL), panel works without military layer enabled
2026-01-26 09:55:36 +04:00
Elie Habib
b6d333c451 Tech variant: use tech-focused AI prompts, ignore politics
- Remove Trump mention from date context for tech variant
- Add variant-aware system prompts:
  - Tech: "Focus ONLY on technology, startups, AI, funding..."
  - Tech: "IGNORE political news, trade policy, tariffs..."
- Use tech-appropriate examples: "OpenAI announced...", "Series B..."
- Bump cache version to v3 to force new summaries
2026-01-25 23:39:38 +04:00
Elie Habib
03a778aa79 Bust stale summary cache with version prefix (v2) 2026-01-25 23:33:03 +04:00
Elie Habib
ecf3829ee0 Fix AI summary cache collision between site variants
The Redis cache key for summaries was built from headlines + mode +
geoContext but did NOT include the site variant (full vs tech). This
caused cross-site cache collisions where a summary generated for the
full variant could be returned to tech variant users (and vice versa).

Changes:
- Pass SITE_VARIANT from frontend to summarization API
- Include variant in cache key: `summary:{variant}:{hash}{geoHash}`
- Updated both groq-summarize and openrouter-summarize endpoints

Now cache keys are scoped per variant, preventing incorrect summaries.
2026-01-25 23:03:22 +04:00
Elie Habib
1bcb098b01 Add curated events fallback for major tech conferences
The dev.events RSS feed is limited to 100 items sorted by "date added"
(not event date), causing major events like STEP Dubai to be pushed out
when newer events are added. Added a curated events list as fallback
for important conferences that may fall off the RSS feed:

- STEP Dubai 2026 (Feb 11-12) - 8,000+ attendees, AI economy focus
- GITEX Global 2026 (Dec 7-11) - World's largest tech show
- TOKEN2049 Dubai 2026 (Apr 29-30)
- Collision 2026 (Jun 22-25) - Toronto
- Web Summit 2026 (Nov 2-5) - Lisbon

Curated events are deduplicated with feed data to avoid duplicates.
2026-01-25 22:59:22 +04:00
Elie Habib
bed2479de4 Merge branch 'claude/add-deckgl-visualization-D1VHX' into main
Adds DeckGL WebGL map rendering for desktop, comprehensive README
documentation, and intelligence synthesis features.
2026-01-25 22:29:25 +04:00
Elie Habib
19e7d9105d Fix LLM knowledge cutoff: add current date context to prompts
LLMs have outdated knowledge (pre-Jan 2025), causing errors like
"former President Trump" when Trump is current president.

Added dateContext to all summarization prompts with:
- Current date
- Trump is current president (second term, Jan 2025)
2026-01-25 17:34:30 +04:00
Elie Habib
13c0e9f771 Fix repetitive 'Breaking news tonight' in all summaries
Problem: Every panel summary started with 'Breaking news tonight:' because
the prompt said 'write like a news anchor opening the evening news'.

Fix: Rewrote prompts to:
- Explicitly forbid 'Breaking news', 'Good evening', 'Tonight' openings
- Remove TV news anchor framing entirely
- Instruct to start directly with subject: 'Iran's regime...', 'The US Treasury...'
- Focus on substance over style

Updated both groq-summarize.js and openrouter-summarize.js
2026-01-25 17:12:23 +04:00
Elie Habib
55fd6cfda3 Add FocalPointDetector intelligence synthesis layer
Correlates news entities with map signals to identify "main characters"
appearing across multiple intelligence streams:

- Extract entities from all 80+ news sources via NER
- Cross-reference with map signals (flights, vessels, outages, protests)
- Score focal points where news + signals converge
- Generate rich AI context for correlation-aware summarization

New files:
- focal-point-detector.ts: Core detection and scoring service
- signal-aggregator.ts: Geographic signal aggregation

UI shows top focal points with urgency badges and signal icons.
AI prompts updated to leverage intelligence synthesis context.
2026-01-25 16:28:29 +04:00
Elie Habib
8348a6782b Fix repetitive summary openings
- Rewrite prompts to vary output (no more "The dominant narrative...")
- Instruct model to lead with substance: location, action, impact
- Add explicit rule: NEVER start with meta-commentary
2026-01-25 15:52:03 +04:00
Elie Habib
1a60bdeee6 Add resizable panels, fix Railway crash, improve AI Insights
- Panel resize: drag bottom edge to span 1-4 grid rows, persisted to localStorage
- Fix HTML5 drag conflict with resize using capture-phase listeners
- Fix memory leaks in Panel.ts (document listeners now cleaned up)
- Fix Railway ERR_HTTP_HEADERS_SENT crash with response flag pattern
- Improve AI summarization prompts to focus on ONE dominant narrative
- Add VIOLENCE_KEYWORDS and UNREST_KEYWORDS for better story discovery
- Add combo bonus for flashpoint + unrest stories (e.g., Iran protests)
- Relax 2-source filter for high-scoring critical stories (score > 100)
2026-01-25 15:39:53 +04:00
Elie Habib
0c2a272bf5 Add backend caching for CII and Strategic Risk scores
- New /api/risk-scores endpoint computes and caches scores in Redis
- Uses ACLED protest data + baseline geopolitical risk factors
- 10-minute cache TTL shared across all users
- CIIPanel and StrategicRiskPanel fetch cached scores on load
- Learning Mode banner hidden when cached scores available
- Eliminates 15-minute warmup for users
2026-01-25 14:39:19 +04:00
Elie Habib
86590cc8b2 Fix AI summarization quality and InsightsPanel prioritization
- Add headline deduplication (60% word similarity threshold)
- Prevent prompt instructions from leaking into output
- Increase max_tokens from 80 to 150 to prevent truncation
- Add multi-tier keyword scoring: military (+80), flashpoint (+60), crisis (+30)
- Demote business/tech news (0.3 penalty) when mixed with conflict keywords
2026-01-25 14:22:16 +04:00
Elie Habib
3280a9e616 Improve AI Insights prioritization and shorten summaries
- Add keyword boosting for critical geopolitical terms (war, armada,
  military, iran, russia, ukraine, etc.) - +40 base + 10 per keyword
- Shorten summaries: max 2 sentences, 40 words, max_tokens=80
- Critical terms now outrank generic "alert" stories
2026-01-25 14:00:14 +04:00
Elie Habib
7e1dfcb160 Improve search results and fix RSS feeds
- Double MAX_RESULTS from 12 to 24
- Prioritize news over static infrastructure in search
- Update News24 URL to post-redirect destination (feeds.capi24.com)
- Add trailing slash to SCMP URL
- Add feeds.capi24.com to both proxy allowlists
2026-01-25 13:51:54 +04:00
Elie Habib
6f65bcece7 Improve summarization prompts to avoid repetitive opening phrases 2026-01-25 13:47:34 +04:00
Elie Habib
b92c501582 Add 13 missing domains to RSS proxy allowlist
Fixes 403 errors for:
- Middle East: Al Arabiya, Arab News, Times of Israel, SCMP
- Regional: Kyiv Independent, Moscow Times, News24
- Int'l Orgs: UN News, IAEA, WHO, CISA, Crisis Group
- Other: Hacker News (news.ycombinator.com)
2026-01-25 13:13:30 +04:00