# Architecture Notes — As-Found Shape

Quick observations for whoever is writing the spec. Not a critique, just what's there.

## The four sats and their relationship to warsat

```
                     ┌────────────────────────────────────┐
                     │  warsat  (military / geopolitical)  │
                     │  • warsat-delta.py   (engine)      │
                     │  • warsat-orbital.py (engine)      │
                     │  • warsat_scan.py    (kill+log)    │
                     │  • threat_actor_indicators.py      │
                     │  • 45 monitors / 6 domains         │
                     └──────────┬─────────────────────────┘
                                │ pattern was meant to be copied
            ┌───────────────────┼───────────────────┐
            ▼                   ▼                   ▼
   ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
   │ repsat          │ │ scosat          │ │ execsat         │
   │ (legislative)   │ │ (judicial)      │ │ (executive)     │
   │ • 8 categories  │ │ • 14 categories │ │ • 16 categories │
   │ • SKILL.md only │ │ • SKILL.md only │ │ • SKILL.md only │
   │ • monitors.json │ │ • monitors.json │ │ • monitors.json │
   │ • (no engine)   │ │ • (no engine)   │ │ • (no engine)   │
   └─────────────────┘ └─────────────────┘ └─────────────────┘
```

The other three are monitor-definition stubs. They were each meant to grow their own `*sat-delta.py` and `*sat-orbital.py` derived from warsat's, but it was never finished. The patterns of "delta comparison" and "orbital platform" are warsat-specific.

## The signal reading pipeline (SIGINT)

```
                    ┌────────────────────────────────────────┐
                    │         COLLECTORS  (run daily)         │
                    │  • signal_collector_reddit_feeds.py    │
                    │  • multi_osint_search{,_final,_real}   │
                    │  • gnews_scraper.py                    │
                    │  • reddit_fixed.py                     │
                    │  • run_scrapers_new.py                 │
                    │  • shipping_tracker.py                 │
                    └────────────────┬───────────────────────┘
                                     │ write raw JSON
                                     ▼
                    ┌────────────────────────────────────────┐
                    │   memory/signal_results/{source}/       │
                    │   19,339 files · 184 MB                │
                    │   gdelt=14,416  newsapi=2,726          │
                    │   newsdata=2,179  reddit=2  ship=16     │
                    └────────────────┬───────────────────────┘
                                     │ read raw JSON
                                     ▼
                    ┌────────────────────────────────────────┐
                    │         ANALYZERS  (run daily)          │
                    │  • signal_analyzer.py           (v1)   │
                    │  • signal_analyzer_premium.py          │
                    │  • signal_analyzer_v2.py               │
                    │  • signal_analyzer_v3_early_warning.py │
                    │  • signal_analyzer_v3_expanded.py      │
                    │  • extract_real_signals.py             │
                    └────────────────┬───────────────────────┘
                                     │ emit findings
                                     ▼
                    ┌────────────────────────────────────────┐
                    │       INTEGRATION / BRIDGING            │
                    │  • sigint_shipping_integration.py      │
                    │  • sigint_healthcheck.py               │
                    │  • convert_real_to_dashboard.py        │
                    │  • dashboard_api_generator.py          │
                    │  • multi_source_monitor.py             │
                    └────────────────┬───────────────────────┘
                                     │
                                     ▼
                            public/sigint/index.html
                            (the public-facing dashboard)
```

The collectors and analyzers communicate by **writing and reading JSON files in `memory/signal_results/`**. There is no shared schema — each `*_1773518868.json` is whatever the collector chose to put in it. The analyzers are responsible for knowing each source's quirks.

## Five iterations of signal_analyzer

I count five Python files:

- `signal_analyzer.py` — original
- `signal_analyzer_premium.py` — "premium" variant
- `signal_analyzer_v2.py` — version 2
- `signal_analyzer_v3_early_warning.py` — version 3 with early-warning focus
- `signal_analyzer_v3_expanded.py` — version 3 expanded

There is no documentation explaining which one is current. The "v3_expanded" filename suggests it's the latest, but the lack of a deprecation/import chain means they're all sitting there, equally executable, and it's anyone's guess which one actually runs in production. Same pattern for `multi_osint_search{,_final,_real}.py`.

## Three "tiers" of input

The `*sat` scanners use a T1–T5 source-reliability system (duplicated between warsat-delta.py and warsat-orbital.py):

| Tier | Label | Sources |
|------|-------|---------|
| T1 | REPORTED | Reuters, AP, BBC, Al Jazeera, CNN, NBC, Axios, CENTCOM, DoD, State.gov, Whitehouse.gov, IAEA, CISA, ADS-B, Marine Traffic, satellite imagery |
| T2 | CONFIRMED | ISW, USNI, institutes, foundations, Wikipedia, Forbes, Bloomberg, FT, Economist, Foreign Affairs |
| T3 | DERIVED | (assigned by inference, not by source) |
| T4 | ASSESSED | Anything with "analysis", "assessment", "expert", "analyst", "likely", "probably" |
| T5 | SPECULATIVE | "anonymous", "unverified", "speculative", "possible", "rumor", "claim" |

Tier weights (1.0, 0.9, 0.7, 0.5, 0.3) are also duplicated across the two warsat scripts.

## The four killswitches

Each *sat has its own:

- `wartrack-switch.json` — warsat (legacy name, before the *sat family naming)
- `repsat-switch.json`
- `scosat-switch.json`
- `execsat-switch.json`

There is no global "kill all satellites" switch. Each has to be flipped individually.

## satellite-keys.json

Holds the API keys for the three non-warsat sats:

- **repsat**: `congress_gov` (real), `propublica_congress` (DEPRECATED, API shut down 2024), `govtrack` (free, no key), `opensecrets` (DEPRECATED, shut down April 2025), `fec` (null)
- **execsat**: `adsb_exchange` (null), `regulations_gov` (real)
- **scosat**: `courtlistener` (real)

Note the duplicated `fec` key entry. And note that two of the listed keys are deprecated — there's no detection/handling of dead keys; calls just fail.

## The dashboard

`public/sigint/index.html` is the human-facing output. It reads from the same JSON files the analyzers write to. The flow is:

```
collectors → signal_results/*.json
                 ↓
analyzers → emit dashboard-shaped JSON
                 ↓
public/sigint/index.html (renders it)
```

There's no formal API; the dashboard presumably reads from disk or hits a tiny local server.

## What's missing entirely

- **Only warsat has any executable code.** The other three sats are monitor-definition stubs.
- **No tests.** Not one.
- **No types.** Just Python 3.10+ annotations.
- **No config file.** All paths, sources, tier keywords hardcoded.
- **No version field on anything.** 19,339 signal-result JSON files with no schema version in any of them.
- **No global "kill all sats" switch.** Have to flip four.
- **No retention policy on `signal_results/`.** 184 MB and growing.
- **Analyzers and collectors communicate by file drop.** No shared schema, no contracts.
- **Five versions of `signal_analyzer*.py` with no supersedence chain.**
- **The SIGINT "shipping integration" is half-wired** — there's an integration script, but the call site isn't obvious.
- **Tier weights and source keywords are duplicated** between `warsat-delta.py` and `warsat-orbital.py`.
- **API keys file has a duplicated `fec` entry** and lists two known-dead keys with no detection.
- **The `intelligence_sources.json` and `threat_actor_framework.md` are loose docs** that some scripts may or may not actually read.
