Target: ARGUS /investments route + Invariant Operator cross-correlation layer Date: 2026-05-18 Origin cycle: 148
The per-actor tracker is incremental (any researcher can build a Bloomberg-lite per-name dashboard). The cross-correlation layer surfaces emergent patterns no individual actor can see - and that's the genuine moat.
Three concrete scoring functions implement this:
This pattern generalizes: - Big-player investment moves (this cycle) - Audit-firm methodology drift across N firms (extension of lessons-library) - Bug-bounty competitor velocity across N hunter accounts (extension of EYE 14-20) - Pejji-client behavior across N SMEs (Pejji BI layer)
Every JSONL disclosure row carries "source": "manual_seed_cycle148". This way, when real scrapers come online (NGX RNS adapter, Nairametrics RSS, Notion DB pull), the rows from those sources can carry distinct source tags and the manual-seed rows decay out of the visible feed naturally. File-level tagging would force a destructive migration; row-level lets the dataset evolve gracefully.
UI surfaces the source tag as a small badge next to each disclosure so operator can mentally weight reliability per row.
Surveyed: - NGX RNS (Real-time News Service): web-only feed, no documented JSON API. Scrape requires session handling + sometimes auth. - Nairametrics: has RSS but coverage is editorial (not raw filings). - BusinessDay corporate-disclosures: web-only. - AfricanFinancials: paywall.
Decision: v0.1 ships with manual JSONL seed under ~/bounty/lessons-library/investments-data/ngx-disclosures.jsonl. The JSONL contract is stable; future scraper adapters (Nairametrics RSS first, then NGX RNS HTML scrape if needed) write to the same file. The Invariant Operator scoring works on whatever rows are in the JSONL - data source pluggable behind the same contract.
The /api/research endpoint must: - Cap input prompt at 4KB - Cap max_output_tokens at 512 (~$0.005-0.05 per call on Sonnet) - Use a stable system prompt that REQUIRES the model to refuse financial advice - Return a safe stub when API key is not configured, so the UI doesn't break during initial deploy
This pattern (stub + real LLM path behind the same response shape) is reusable for any Worker that calls a paid external API.
Same pattern reused from Cycle 146 /lessons: 1. Compute sha256 of all data inputs 2. Compare to state file 3. Skip if unchanged, else regenerate + wrangler pages deploy
For /investments, the input set is players.json + ngx-disclosures.jsonl + macro-signals.json + thesis/*.md. Cron-friendly idempotency; wrangler API rate-limit safe.
Multi-surface disclaimer: - Visible warning banner near top of /investments and every drill-in page - Footer reaffirmation - LLM system prompt that explicitly bans recommendations - Each thesis card has explicit INVALIDATION-CONDITIONS section so the operator (and any reader) sees how the analysis falsifies, not just how it confirms
This is risk hygiene for the operator (regulatory + reputation) and intellectual hygiene for the analysis (forces the analyst to articulate falsification ex-ante).
The seeded NGX disclosure rows have null shares + null value_ngn. That's correct - we don't have those numbers, so we represent the absence explicitly with null, not with fabricated estimates. Schema permissiveness > schema fabrication.
The 3 scoring functions are deterministic Python with explicit thresholds. They are auditable, replicable, and falsifiable. If we replaced them with "ask the LLM what's interesting," we would: - Lose reproducibility - Add per-cycle cost - Make it impossible to A/B different threshold settings - Drift toward overconfident summary-style outputs
The Invariant Operator surfaces three CLASSES of signal explicitly because those are the three real cross-correlation mechanics: convergence (alignment), divergence (conflict), and meta-trigger (impact propagation).
The /api/research Worker validates Cf-Access-Authenticated-User-Email header. The CF Access edge is the primary gate; the Worker's email-allowlist is defense-in-depth. Both are required because:
- CF Access could be misconfigured
- A token leak shouldn't yield free LLM access
- Operator-only research keeps the moat private
~/bounty/argus/argus-investments-feed.py (scraper stub + 3 scoring functions + alert diffing)~/bounty/argus/argus-investments-gen.py (HTML generator)~/bounty/argus/argus-investments-sync.sh (hash-gated cron driver)~/bounty/argus/dashboard/api/research-worker.js (LLM prompt-box Worker)~/bounty/argus/dashboard/investments/index.html + per-player + per-thesis HTML (generated)~/bounty/lessons-library/investments-data/players.json (12-player seed)~/bounty/lessons-library/investments-data/ngx-disclosures.jsonl (7-row seed)~/bounty/lessons-library/investments-data/macro-signals.json (5-signal seed)~/bounty/lessons-library/investments-data/thesis/*.md (4 thesis cards)