7 Commits
Author SHA1 Message Date
dennisthiessenandClaude Opus 5 83fe76c506 fix(sec): alert when a filing gap's reprieve lapses instead of re-pausing quietly
An escalated gap stops pausing setups while the issuer's own fundamentals are
still recent. That reprieve ends on its own — the stored filings age past
GAP_GATE_RECENT_FILING_DAYS, or a newer gap arrives and the all-escalated
condition fails — and nothing reported either, because filing_gap_aged only
escalates gaps whose escalated_at is NULL and so never fires twice for the same
gap. For the 43 issuers behind the previous commit that lands around
2026-10-26, when their late-April filings age out together.

sec_filing_gaps.exempted_at (migration 034) makes the transition observable:
stamped quietly while the issuer is exempt, cleared when the exemption lapses,
and the clear is what raises filing_gap_repaused — once per lapse, re-arming if
the issuer's data recovers and ages out again. A gap that was never exempt has
no transition and stays silent; it is simply still paused, which
filing_gap_aged already said.

gap_exempt_ciks is public so the importer alerts on membership changes in
exactly the set the gate reads, rather than restating the rule.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016Lo99z3jWqu9X9ueBU3Z3D
2026-08-21 17:44:04 +02:00
dennisthiessenandClaude Opus 5 a13dbc9710 fix(sec): stop an unrecoverable filing gap pausing setups forever
A filing gap pauses its issuer until the filing is ingested or a later one
supersedes it, which assumes the gap is temporary. It is not always: SEC's
per-company Company-Facts files can go stale indefinitely — 43 large caps
whose Q2 10-Qs the frames API carries but whose companyfacts files never
received (Abbott's newest fact was 2026-04-29 in late August) — and because
the supersede rule needs a *successfully ingested* later filing, a stale file
swallows the next quarter too. The pause was open-ended, not seasonal.

So the pause hands off to the alert: once filing_gap_aged has escalated a gap,
it stops gating if the issuer's newest stored 10-K/10-Q is under 180 days old.
An issuer with nothing that recent has no usable fundamentals at all and stays
paused, which is the case the gate was built for.

Applied in the gate service only. active_gaps is deliberately untouched so
_retry_backlog keeps retrying and a recovered filing still resolves normally,
and the bound covers both gate paths — the queue and the validation_json
summary that mirrors the same filings — since bounding one leaves production
behaviour unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016Lo99z3jWqu9X9ueBU3Z3D
2026-08-21 16:46:28 +02:00
dennisthiessenandClaude Opus 5 3e83d63b05 chore: decommission FMP, Finnhub and Alpha Vantage (A6)
The A5 cutover has been on and observed in production, so SEC Company Facts +
DoltHub earnings are already the live source for `fundamental_data`. This
removes everything the legacy path still occupied.

Gone: the three providers and their config/env keys; the weekly
`fundamental_collector` job; the cutover toggle (SEC + Dolt is now the
unconditional path, so `off` can no longer silently freeze scoring inputs); the
A5 parity report, whose deltas became structurally zero once the candidate
builder started writing the table it compared against; and the FMP tier of
universe bootstrap.

Two behavioral notes:

- Disabling **SEC Fundamentals Import** now stops the SEC network fetch only.
  The local cache refresh moved outside the job-enable check, because candidates
  also derive from daily closes and earnings events — freezing those on an
  ingestion pause would stale scoring with no fallback left to recover from.
- `/ingestion/fetch?sources=fundamentals` still accepts the key and reports
  `skipped`; there is no per-ticker fetch any more.

Migration 029 does not blanket-delete the leftover settings rows. Migrations run
before the service restart, and pre-A6 code reads an absent `job_*_enabled` row
as *enabled* — so the two behavior-bearing keys become tombstones pinned to safe
values (hidden in Admin) and only the inert three are deleted. Removing the
provider keys from the production `.env` is the matching rollout step.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 11:19:28 +02:00
dennisthiessen f49b422095 fix: close remaining ingestion review gaps 2026-08-04 08:55:30 +02:00
dennisthiessen 59ac108c90 perf: scope SEC ticker quality checks 2026-08-04 08:09:37 +02:00
dennisthiessen 4c0c0579f5 fix: make SEC quality gating terminal-safe 2026-08-04 07:58:18 +02:00
dennisthiessen 3a6900d45a fix: gate setups on SEC filing completeness 2026-08-03 23:47:07 +02:00