What this is, and what it isn't
A composite scoring engine that ingests real signals from three independent, free, public APIs — SEC EDGAR full-text search, GitHub (REST + Search), and Hacker News (Algolia) — resolves them to canonical entities, and combines them with a documented model. No synthetic data anywhere in this repo; every signal is a real, dereferenceable record from a live API call.
Not a real prospect list. The 14 entities scored below are large public SaaS companies, chosen for exactly one reason: verifiable coverage across all three signal sources. They are not realistic outbound targets for a solo GTM consulting practice — they exist purely so the fusion mechanism could be proven against real, independently-checkable data instead of invented records.
The three sources, and why each is real
| Source | What it gives | Confidence |
|---|---|---|
| SEC EDGAR full-text search | 8-K filings, keyed by CIK, ranked by disclosed item | 0.95 — CIK unambiguous |
| GitHub REST + Search API | Release-cadence change for the org's highest-starred repo | 0.90 — org slug unambiguous |
| HN Algolia Search API | Story mentions, severity = the story's own point count | 0.60 — name-string matching, see below |
No API key for any of the three. SEC asks only for a descriptive User-Agent, which this repo sends.
The scoring model — every constant explained, none tuned
- Recency is exponential decay, half-life 30 days — chosen over linear decay because it never needs a hard cutoff.
- SEC severity comes from the filing's own disclosed 8-K item code — Item 1.03 (bankruptcy) ranks above Item 5.02 (officer departure) above Item 9.01 (exhibits only), a rubric built from SEC's own item definitions.
- GitHub severity is the org's trailing-90-day release count relative to its own prior-90-day window — an absolute count means nothing without a baseline.
- HN severity is the story's real point count, capped at 100 — HN's own crowd-judged signal, not a proxy invented for this project.
- Cross-source aggregation is noisy-OR (1 − Π(1−si)), not a sum (would let ten weak HN mentions outscore one confirmed SEC bankruptcy filing) and not a max (would throw away what multi-source fusion is for — two sources corroborating one entity is real additional evidence).
This rule has not been validated against real outcomes — it's the documented starting point, not a proven one. That validation is exactly what correlate_with_replies.py is waiting to do — see below.
Entity resolution — the one place this can go wrong, and how it's handled
SEC and GitHub signals are keyed to an unambiguous identifier before a request is even made. HN starts from free text, so dedup.py matches a story's title against each entity's canonical name (whole-word, case-sensitive). If zero or more than one entity matches, the hit is dropped, not guessed — a two-company story doesn't get arbitrarily assigned to one of them.
HN's search matches far more than titles. Inspecting Okta's zero-resolved run by hand: Algolia's query=Okta returned real stories where the literal word "Okta" never appeared in the title — the match came from body text, URL, or comments. Short or common company names (Okta, Twilio, Asana) see a much higher resolution-drop rate than distinctive ones (Cloudflare, GitLab) — not because they're less newsworthy, but because Algolia's search surface is broader than the field this engine actually checks. The conservative choice (drop rather than guess from body text) was kept deliberately; real drop rates are reported per-entity in the fetch log, not averaged away.
What broke on the first real runs
SEC EDGAR bare-500'd on 3 of 14 entities mid-run, confirmed transient — the exact failing request, re-issued by hand seconds later, succeeded every time. The first run's script had no retry and would have silently shipped an 11/14 dataset.
A later run hit widespread connection resets across both api.github.com and hn.algolia.com simultaneously, while a plain curl loop against the same hosts succeeded 5/5 immediately after — consistent with transient local network conditions, not a server-side outage.
Both incidents are fixed with the same mechanism: retry.py, bounded exponential backoff, applied uniformly to all three sources' network calls, not just the one that failed first. The third rerun came back with 456 signals across 14/14 entities and zero errors. All three runs' outcomes are described in this repo, not just the clean one.
Verified run — clean, zero errors
456 signals across 14/14 entities, zero fetch failures logged. HN: 573 hits returned, 266 dropped on entity resolution (46%) — the conservative-resolution tradeoff above, measured, not hidden.
| Rank | Ticker | Composite | Signals (SEC / GitHub / HN) |
|---|---|---|---|
| 1 | NET (Cloudflare) | 1.0000 | 18 / 1 / 51 |
| 2 | SNOW (Snowflake) | 0.9039 | 8 / 1 / 35 |
| 3 | MNDY (monday.com) | 0.8983 | 0 / 1 / 0 — one high-severity GitHub signal alone |
| 12 | MDB (MongoDB) | 0.4165 | 7 / 0 / 38 |
| 13 | CRWD (CrowdStrike) | 0.3137 | 10 / 0 / 3 |
Full table in output/scored-entities-2026-08-23.csv. Raw per-signal evidence (every SEC filing URL, GitHub releases page, HN story link) in output/all-signals-2026-08-23.json.
Reproduce it
python3 -m venv .venv ./.venv/bin/pip install -e ".[dev]" ./.venv/bin/pytest -q # 44 tests, offline, against committed fixtures ./.venv/bin/python scripts/fetch_live_signals.py # real live run, ~3-4 min
Committed fixtures (real API responses captured 2026-08-23) let the test suite run fully offline; fetch_live_signals.py is the only thing that touches the network, and it's what produced every file in output/.
What this doesn't prove
- The scoring model is unvalidated. Severity rubrics and the noisy-OR aggregation are documented, defensible starting points, not measured against any real outcome.
correlate_with_replies.pyis built and ready; it has never run against real data because the sequencing infrastructure it needs doesn't exist yet. - This is not a prospect list — see above.
- HN resolution is conservative by design, which means real recall loss on common/short company names.
- One SEC 500 incident, observed once. The retry fix is real and tested, but this is one data point on SEC's reliability, not a statistically established failure rate.
Files
src/signal_engine/entities.py canonical entity list — real tickers/CIKs/GitHub orgs src/signal_engine/scoring.py Signal dataclass, severity rubrics, decay, noisy-OR aggregation src/signal_engine/dedup.py HN title -> canonical ticker resolution, ambiguity handling src/signal_engine/retry.py bounded exponential backoff (added after a real SEC 500) src/signal_engine/correlation.py Spearman rho, stdlib only src/signal_engine/engine.py aggregates Signals into a ranked entity table scripts/fetch_live_signals.py the only network-touching script; produces everything in output/ scripts/correlate_with_replies.py blocked on real reply data — fails loudly, on purpose fixtures/ real API responses, captured 2026-08-23, offline tests output/ real committed run output — scored table, raw signals, fetch log tests/ 44 tests: scoring math, dedup, retry, correlation, fixture-parsing
Built something similar for your stack?
I build signal-detection, enrichment and outbound systems inside your own tools. You own everything — nothing is locked to me.