mirror of
https://github.com/0xrsydn/idx-cli.git
synced 2026-08-07 01:33:52 +00:00
Refactor KSEI PDF parsing for the live above-1 holder-register layout, add IDX announcement discovery plus browser-impersonated PDF fetches, and update the ownership docs to mark Batch 1 complete and scope Batch 2 around above1 hardening and unsupported legacy inputs.
15 KiB
15 KiB
idx-cli TODO
✅ Completed (v0.1.0)
- Provider abstraction (MarketDataProvider trait, Yahoo impl)
stocks quote <SYMBOL...>— real-time quotes, multi-symbolstocks history <SYMBOL>— historical OHLC data- File cache with TTL + offline mode + stale-cache fallback
- Config system (TOML file, env vars, CLI flags, precedence)
- Output modes: table (human) + JSON (agent)
- 52-week range bar in quote table
cache info/cache clearconfig init/get/set/path- Pre-commit hooks (fmt, clippy, test)
- GitHub Actions CI
- Nix flake + devshell
- MIT license
- crates.io metadata
✅ Completed (v0.1.1)
- Technical analysis module (SMA, EMA, RSI, MACD, volume ratio)
- Signal interpretation (bullish/bearish/neutral consensus)
stocks technical <SYMBOL>— full technical analysis command- Colored signal output (green/red/yellow)
- 1-year lookback for SMA200 coverage
✅ Completed (v0.1.1 — fundamental suite)
stocks growth <SYMBOL>— revenue/earnings growth with signalsstocks valuation <SYMBOL>— PE, PB, ROE, margins, EV/EBITDA with signalsstocks risk <SYMBOL>— D/E, current ratio, ROA with signalsstocks fundamental <SYMBOL>— composite growth + valuation + riskstocks compare <SYM1,SYM2,...>— side-by-side multi-symbol comparisonanalysis/fundamental.rs— fundamental analysis module (ported from idx-mcp)- Yahoo quoteSummary endpoint parser (/v10/finance/quoteSummary)
- 142 tests passing (94 unit + 48 integration)
✅ Completed (2026-03-26 — hardening pass)
- Unified cache, offline, stale-cache, and
--no-cachebehavior across core and MSN-only stock commands - Rejected the conflicting
--offline --no-cacheflag combination explicitly - Routed startup/config failures through the same JSON-aware error path as runtime failures
- Validated
stocks screen --filterand--region; invalid values now return errors - Added regression tests for startup JSON errors, MSN profile offline/stale-cache behavior, and screener validation
✅ Completed (2026-03-26 — MSN output cleanup)
- Re-mapped live MSN
profileoutput to prefer localized/company fields for name, description, sector, industry, website, address, and phone - Reworked
stocks insightsoutput to derive a real summary, split highlights vs risks from evaluation status, and populatelast_updated - Fixed signed-number formatting so
stocks financialstable output no longer mangles negative values - Added live-like fixtures and regression coverage for
profile,insights, and signed table formatting
🚧 Next Up
- Build a reusable live smoke script/checklist for all shipped CLI commands (
scripts/live-smoke.sh,docs/SMOKE.md) - Re-run full live smoke for MSN-only commands after the cache/offline, mapping, and formatting fixes (
scripts/live-smoke.sh --mode full --group live-table --group live-json) - Review remaining noisy table output in
financialsandearningsbeyond the signed-number fix - Expand parser/CLI regression coverage for the rest of the MSN-only command set
- Keep the live-smoke notes below in sync with real command output after each hardening pass
🚧 Ownership Roadmap Reset (2026-03-29)
Batch 1 — IDX discovery + remote PDF import
- Verify and document the IDX announcement/listing page that exposes the monthly ownership PDF link
- Verified official BEI listing page:
https://www.idx.co.id/id/berita/pengumuman/ - Verified listing page JSON source used by the site:
GET /primary/NewsAnnouncement/GetAllAnnouncement?keywords=...
- Verified official BEI listing page:
- Implement discovery/crawler logic for the hashed IDX PDF asset URL instead of hardcoding monthly paths
- Expose discovery as an explicit
idx ownership discoverCLI surface so the live BEI feed can be inspected without coupling it to import - Extract a reusable browser-impersonated fetch helper for ownership downloads by reusing the repo's
curl-impersonatepattern - Wire
ownership import --urlto the impersonated fetch path for IDX-hosted PDFs - Keep the current PDF parser/import path as the first production ingest route
- Add tests and fixtures for IDX announcement-page parsing plus remote PDF fetch failure modes
- Batch 1 verification:
cargo build - Batch 1 verification:
cargo clippy -- -D warnings - Batch 1 verification:
cargo test - Batch 1 verification: fixture-backed parser/downloader tests cover announcement discovery, hashed URL extraction, and downloader failure cases
- Batch 1 verification: live
idx ownership discover --family above1 --limit 2innix developresolves the current BEI hashed URLs for the parser-compatibleabove 1%report family - Batch 1 verification: live end-to-end import succeeds for one discovered BEI ownership PDF URL
- Batch 1 verification: end-to-end import into a temp ownership DB via
idx ownership import --url ..., followed byidx ownership releasesand one ticker query- Resolved root cause on
2026-03-29:- the parser was already correct for the holder-register schema; the missing piece was discovery support for the
Pemegang Saham di atas 1% (KSEI)family - the parser-compatible source is the
lamp1attachmenthttps://www.idx.co.id/StaticData/NewsAndAnnouncement/ANNOUNCEMENTSTOCK/From_EREP/202603/b9b638e5a8_8928aca255.pdf - the
above 5%andinvestor-typeBEI families remain different schemas; as of2026-03-30, they should be treated as legacy / unsupported input rather than new parser targets
- the parser was already correct for the holder-register schema; the missing piece was discovery support for the
- Resolved root cause on
Batch 2 — Above-1 hardening and unsupported-input UX
- Standardize the supported remote-import contract on the
Pemegang Saham di atas 1% (KSEI)holder-register layout and itslamp1attachment shape - Add BEI PDF schema classification before parse/import so
ownership import --urlcan reject non-holder-register PDFs before the parser runs - Improve CLI error messages and fallback behavior for discovery failure, fetch failure, invalid remote content, and known-but-unsupported legacy BEI schema variants
- Capture live-like fixtures for the current discoverable
investor-typeandabove 5%BEI attachments (or theirmutoolstextextracts) so unsupported-input detection and failure UX are regression-tested - Decide and document whether
ownership discovershould default toabove1output while keeping legacy families available only for diagnostic use - Decide and document whether
ownership import --urlaccepts only direct PDF URLs or can also accept an IDX listing page as input - Add regression coverage for Cloudflare/HTML responses, missing announcement links, duplicate release imports, and unsupported BEI schema detections
- Batch 2 verification:
cargo build - Batch 2 verification:
cargo clippy -- -D warnings - Batch 2 verification:
cargo test - Batch 2 verification: ownership-focused smoke checks cover successful remote import plus expected failure UX
Batch 3 — Snapshot publishing + sync
- Design maintained SQLite snapshot publishing after remote IDX import is stable
- Add
idx ownership sync - Define manifest/checksum/update semantics and local DB replacement rules
- Add regression coverage for manifest parsing, checksum validation, no-op sync, and forced refresh
- Batch 3 verification:
cargo build - Batch 3 verification:
cargo clippy -- -D warnings - Batch 3 verification:
cargo test - Batch 3 verification: sync installs into an empty temp data dir, preserves query behavior, and no-ops when already current
Batch 4 — KSEI ZIP/TXT fallback and cross-check path
- Keep KSEI ZIP/TXT ingest as fallback and validation/backstop work, not the first milestone
- Define whether the KSEI archive is only a maintainer fallback or a user-facing alternative import source
- Add cross-check coverage between IDX-PDF-derived output and KSEI-archive-derived output for at least one monthly release
- Batch 4 verification:
cargo build - Batch 4 verification:
cargo clippy -- -D warnings - Batch 4 verification:
cargo test - Batch 4 verification: fallback ingest produces a compatible SQLite state for
ownership releases,ticker, andchanges
📋 Backlog (per SPEC.md)
market summary— IHSG index, market breadthmarket movers— top gainers/losers/volumemarket sectors— sector performance overviewscreen query "<EXPR>"— filter stocks by expressionscreen presets/screen run <PRESET>— built-in screener presetswatchlistcommands — create, manage, live watchalertssystem (v0.2+) — price alerts with daemoncompletions <SHELL>— shell completion generation- CSV/TSV output formats
- Additional providers (Alpha Vantage, Twelve Data, IDX official)
🔬 Latest Smoke Findings (2026-03-28)
- Live smoke passed for shipped
stockscommands:quote,history,technical,growth,valuation,risk,fundamental,compare,profile,financials,earnings,sentiment,insights,news,screen - Yahoo routing verified for live
quoteandhistory stocks history --history-provider msncorrectly fails for IDX as unsupportedownership releasesworks with a writableownership.db_pathand an empty DB- Regression coverage now verifies offline/cache parity for MSN-only commands (
stocks profile BBCA) --offline --no-cachenow fails fast as an invalid flag combination instead of serving cache- Config/startup failures now honor the JSON error contract (
IDX_PROVIDER=bogus idx -o json version) - Invalid
stocks screen --filter/--regionvalues now return validation errors - Added reusable smoke runner/checklist for shipped CLI surfaces (
scripts/live-smoke.sh,docs/SMOKE.md) - Reusable smoke runner passes on deterministic mock suites:
general/cache/routing/errors/ownership= 32/32 and shippedstocksmock matrix = 30/30 (tmp/live-smoke/20260326-194907,tmp/live-smoke/20260326-194914) - Full live MSN-only smoke now passes via runner for both table and JSON surfaces: 30/30 (
tmp/live-smoke/20260326-195853) - Targeted no-cache live checks confirm
profile,insights, andfinancialsfixes against real MSN responses - Live
stocks profile BBCAno-cache output now populates company/localized fields instead of the sparse top-level fallback - Live
stocks insights BBCAJSON now returns a mixed-signal summary plus non-emptylast_updated - Live
stocks financials BBCAtable no longer renders malformed negative numbers - Re-run full live smoke to reconfirm all MSN-only commands after the latest hardening fixes
stocks financials BBCAtable now trims ISO timestamps from section headers and humanizes raw line-item keysstocks earnings BBCAtable now splits history vs forecast and formats annual periods, revenue values, and dates for table mode- Fixture-backed parser and CLI JSON regression coverage now covers the remaining MSN-only
sentiment,news, andscreencommands - Fresh post-coverage live MSN smoke rerun still passes for table and JSON surfaces: 30/30 (
tmp/live-smoke/20260327-163403) ownership import --fetch-bingis still deferred and returns unsupported- Real KSEI PDF import from local file now works again:
ownership import --file /Users/rasyidanakbar/Downloads/ksei_raw_data.pdfimported7261rows for955tickers on2026-03-28, replacing the previous6-row/1-ticker failure mode - KSEI parser no longer depends on the old hardcoded column bounds fixture layout; it now reconstructs rows from
mutoolline output and handles the liveDATE + SHARE_CODEmerged segment plusD/Alocality markers - A real IDX-hosted March 2026 ownership PDF URL was verified on
2026-03-29, but only throughcurl-impersonateinsidenix develop; plaincurlstill returns403from Cloudflare for the same asset - The current repo now has a concrete IDX-first roadmap: discover the hashed PDF URL from IDX pages, fetch it with browser impersonation, and only then layer snapshot publishing and
ownership sync - The KSEI archive (
https://web.ksei.co.id/archive_download/holding_composition) was verified as a secondary upstream that exposes monthly ZIP files and remains useful for fallback/cross-check work - Remote IDX discovery now targets the official BEI
Pengumumanfeed (/id/berita/pengumuman/) and its backing JSON endpoint (/primary/NewsAnnouncement/GetAllAnnouncement), which exposes hashed attachment URLs for ownership-related reports - New
ownership discoverCLI output now shows the latest hashed BEI ownership URLs across the currentabove 5%,above 1%, andinvestor-typereport families ownership import --url https://www.idx.co.id/...pdfnow uses the same browser-impersonated download path as Yahoo auth- Reverse-engineering the current BEI feed shows the discoverable
Pemegang Saham di atas 1% (KSEI)lamp1attachment matches the known-good raw KSEI holder-register layout and now imports successfully - Live
ownership import --urlagainst the discoveredabove 1%BEIlamp1attachment (b9b638e5a8_8928aca255.pdf) now succeeds end to end:7261rows for955tickers on2026-03-29, followed by successfulownership releasesandownership ticker AADI --source ksei - Product scope decision on
2026-03-30: standardize supported remote import on the discoverableabove 1%holder-register family; treatabove 5%andinvestor-typePDFs as legacy / unsupported input - Live
ownership import --urlchecks against the currently discoverableabove 5%andinvestor-typeBEI PDFs still fail withno KSEI rows parsed from PDF, which is expected until unsupported-family detection / rejection UX lands - Live
mutoolinspection of the current discoverableinvestor-typeBEI attachment shows a stock-level aggregate matrix (DATE,STOCK_CODE,NUMBER_OF_SHARES, investor-type columns, holder-size buckets), not the holder-level KSEI register schema the current parser imports - Live
mutoolinspection of the current discoverableabove 5%BEI attachment shows a member/tampungan report (INVS, member names,KSEI UNTUK CLOSED MEMBER-...labels), not the raw KSEI holder-register layout
🐛 Known Issues
- Yahoo Finance returns 429 from datacenter IPs occasionally
- SMA200 trend shows "Insufficient data" if Yahoo returns < 200 candles
- KSEI ownership parser no longer leaks adjacent columns into
INVESTOR_NAMEon the March 2026 live PDF; direct CLI verification now returns clean holders likeAGUNG PERKASA INVESTINDO/CP/L - Yahoo quoteSummary crumb auth — fixed via curl-impersonate-chrome (curl_chrome131)
- fc.yahoo.com → A3 cookie + query1 getcrumb → crumb, both sent to quoteSummary
- Requires nixpkgs#curl-impersonate-chrome in PATH (added to flake.nix + clan-private)