Skip to content

Replace LLM ticker discovery with a curated Ticker Profile - #1060

Merged
kevinhermawan merged 1 commit into
mainfrom
feat/ticker-profile
Jul 28, 2026
Merged

Replace LLM ticker discovery with a curated Ticker Profile#1060
kevinhermawan merged 1 commit into
mainfrom
feat/ticker-profile

Conversation

@kevinhermawan

Copy link
Copy Markdown
Contributor

What changed

Query-analysis used to ask an LLM who a ticker's competitors and regulators were, then cache the answer in ticker_discovery for 14 days. Those answers were guesses: unverifiable, capped at six competitors, and re-derived from IDX classification that is wrong or stale for a meaningful number of issuers. AIMS is filed as coal but exited in 2023. BATA is filed as footwear manufacturing but stopped making shoes in 2024. GMFI is filed as an airport operator but actually does aircraft MRO.

A curated reference file replaces the guess. seed-data/ticker-profiles.json holds 949 issuers with verified competitors, regulators, aliases, prose, and a four-level classification in both Indonesian and English. It is uploaded through the dashboard, the same way IDX tickers already are.

How it works

TickerProfile is a new table, one row per ticker, populated by an admin JSON upload rather than a seed script — so correcting the data is a re-upload, not a redeploy. A read-only Ticker Profiles table renders what was loaded.

The agent no longer runs a discovery LLM call at all. Recon still fires, because it is the only thing supplying current headlines to query generation, but it now builds its searches from curated competitors instead of guessed ones. A ticker with no profile still runs, degrading to own-company only with a warning, so a newly listed issuer is never blocked.

Article-analysis relevance gating and content-generation both read the profile now. Gating aliases went from [symbol, name] to symbol, name, ticker aliases, profile aliases, competitor names and their aliases. The newsletter competitor list was empty in practice and is now populated.

Notes for review

Classification is stored in both languages on purpose. The relevance gate word-matches these strings against Indonesian article text. Storing only the English side would have quietly reduced matching with no error and no failing test.

sub_industry is no longer a relevance match term. After curation it is unique across all 949 rows and averages five-plus words, so it could never match an article. It remains as prompt context.

The upload payload is about 2 MB, which exceeds the default Next.js Server Action body limit, so the dashboard limit is raised to 16 MB.

Removed: ticker_discovery (table, service, two routes, contract types), the 14-day TTL, contract-version cache invalidation, discover-entities.ts and its schema, four DISCOVERY_* constants, and issuer-context.ts.

Verification

Full pnpm code-quality passes: 108/108 tasks, lint, typecheck, tests and Prettier across the workspace.

The migration swaps ticker_discovery for ticker_profile. It is applied locally but applying it to production is a separate deploy decision — the drop is not reversible.

Related issues: Closes #1058

Query-analysis asked an LLM who each ticker's competitors and regulators
were, then cached the guess in ticker_discovery for 14 days. The answers
were unverifiable, capped at six competitors, and derived from IDX
classification that is stale or wrong for a meaningful set of issuers.

A hand-curated, search-grounded profile now supplies that landscape for
949 issuers, uploaded through the dashboard like the existing IDX import.
The discovery LLM call, its cache table, TTL and contract-version
invalidation are gone; recon still runs but builds its queries from
curated competitors. Article-analysis gating and content-generation read
the profile too, so both stop depending on the knowledge graph.
@kevinhermawan
kevinhermawan merged commit 4c5c53f into main Jul 28, 2026
24 checks passed
@kevinhermawan
kevinhermawan deleted the feat/ticker-profile branch July 28, 2026 09:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Replace LLM ticker discovery with a curated Ticker Profile

2 participants