feat(compute): wire country + exchange listing metadata into main.py (PR-A2)#349
Merged
Conversation
…(PR-A2) Populate the StockDetail.exchange / .country fields PR-A1 (#347) declared, plus the Rule-18 Metadata.exchange_coverage_pct diagnostic, from the Step-8 per-ticker cross_source loop. Display-only -- no ranking / scoring / valuation / defense-layer change; NO schema change (stays 0.10.12-phase4.6, the fields already exist from PR-A1). - Import country_for_exchange / exchange_name / fetch_yfinance_exchange. - Two {exchange,country}_by_ticker accumulators before the Step-8 loop. - Per-ticker fetch_yfinance_exchange piggybacks the cross_source market-cap block; skip-safe via QR_SKIP_CROSS_SOURCE inside the helper (no main.py branch -- confirmed no QR_SKIP_CROSS_SOURCE ref in main.py). - exchange= / country= kwargs on StockDetail (siblings of industry=). - exchange_coverage_pct via a pure _exchange_coverage_pct helper, imported by the tests (NOT copied) per the CLAUDE.md PR #310 no-verbatim-copy lesson; + "Exchange coverage" log + the Metadata kwarg. PR-B (hero country/exchange chips) waits for >= 1 cron confirming coverage (observability-before-wiring). Tests +19 (test_main.py orchestrator wiring + test_output/test_exchange_schema.py schema round-trip); full offline suite 1460 passed, 0 failures. Pre-push gate: quantrank-reviewer READY-TO-PUSH, phase-coordinator LOCKSTEP-SATISFIED, docs-reviewer DOCS-CLEAN. https://claude.ai/code/session_0148EoMmL6zakDWqHXjqQ9yq
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
…3A5J # Conflicts: # PHASE_STATUS_INFLIGHT.md
Contributor
Pre-merge production simulation
Diff vs main
Main baseline: Top-10 movers (sorted by |Δcomposite_score|)
|
This was referenced Jun 1, 2026
dackclup
added a commit
that referenced
this pull request
Jun 1, 2026
Replace the stock-detail hero #rank-row sector + industry chips with a country chip (country-flag-icons flag + ISO tag) + an exchange chip (lucide Landmark generic icon + display name), reading detail.country / detail.exchange (populated by PR-A2, #347 -> #349). Display-only; no compute / schema / scoring / valuation change. - New frontend/components/ListingChips.tsx -- LedgerCraft neutral-steel chips (mirrors SectorChip), null-safe (renders nothing until a cron populates the fields), FLAG_BY_COUNTRY static per-country lookup (US today). - New dep country-flag-icons ^1.6.17 (MIT, 0 transitive, 0 install-script -- dependency-auditor + security-reviewer both SAFE). Per-country STATIC subpath import only; barrel/dynamic = 330KB footgun (new CLAUDE.md Gotcha, mirrors lucide). - frontend/app/stock/[ticker]/page.tsx -- swap SectorChip + industry span for ListingChips; drop the now-unused SectorChip import. Sector still shows in the HeroAttributeTiles Sector tile. Held Draft -- merge after the next weekly cron populates exchange/country + confirms exchange_coverage_pct (observability-before-wiring); current data has the fields null so the chips render nothing on live until then. frontend-design-reviewer 0 FAIL (D1 font-medium + D2 flag/icon height parity + F1 title a11y all fixed). tsc --noEmit clean; next build 506/506 static pages; flag tree-shaken (~2KB, no barrel bloat). https://claude.ai/code/session_0148EoMmL6zakDWqHXjqQ9yq Co-authored-by: Claude <noreply@anthropic.com>
dackclup
added a commit
that referenced
this pull request
Jun 2, 2026
…s) (#373) Frontend (6): - PriceHistoryChart: add dark: variants to up/down reference chips; ring-rose-300→200 - RawMetricsTable: add font-mono to numeric value cells - ScoreGauge: add role="img" + aria-label(Math.round) + svg aria-hidden - RankingTable: 2× loose-null (!== null && !== undefined → != null) - RiskSummaryCard: ring-amber-300 → ring-amber-200 (globals.css allowlist) Security (1): - manual-trigger.yml: route inputs.note through env: var (script injection guard) Docs (5): - CLAUDE.md/PHASE_STATUS.md/WORKFLOW.md: schema pointer 0.10.11 → 0.10.12 - METHODOLOGY.md: ~21 currently emit → ~27 currently emit - SKILL.md: "is PR-A2" → "was PR-A2 (merged as PR #349)" (past tense) https://claude.ai/code/session_01ELWfJoJp5kMje2j4zoUCQh Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PR-A2 — country + exchange
main.pywiringSecond of the 2-PR ingest sequence. PR-A1 (schema +
cross_sourcehelpers) merged via #3475f39d644; PR-A2 populates the fields PR-A1 declared. PR-B (frontend hero chips) is still deferred until ≥ 1 cron confirms coverage (observability-before-wiring).Display-only — no ranking / scoring / valuation / defense-layer change. No schema change —
SCHEMA_VERSIONintentionally stays0.10.12-phase4.6(the 3 fields already exist from PR-A1, so no snapshot regen / notest_config.pybump / no SKILL.md row).The 6 edits to
run_weekly_computecountry_for_exchange/exchange_name/fetch_yfinance_exchangefromcompute.ingest.cross_source.exchange_by_ticker/country_by_ticker(dict[str, str | None]) before the Step-8 per-ticker loop.cross_source_validate_market_capblock):exchange_code = fetch_yfinance_exchange(ticker)→exchange_name(...)/country_for_exchange(...). Skip-safe: the helper honorsQR_SKIP_CROSS_SOURCEinternally (nomain.pybranch — confirmed no such ref inmain.py), so simulate does no livefast_infofetch.exchange=/country=kwargs onStockDetail(...).exchange_coverage_pctvia a pure_exchange_coverage_pcthelper (Rule-18 diagnostic) + an "Exchange coverage"logger.info.exchange_coverage_pct=kwarg onMetadata(...).Tests (+19)
tests/test_main.py(9): coverage formula (all/partial/none/empty/rounding) + Step-8 mapping contract (known code → NASDAQ/US · None → both None · non-USXLONpassthrough · None-safety), monkeypatchingcompute.main.fetch_yfinance_exchange.tests/test_output/test_exchange_schema.py(10):Metadata.exchange_coverage_pct+StockDetail.exchange/.countryround-trip (float/zero/default-None / passthrough / both-populated / both-None)._exchange_coverage_pctrather than copying it (CLAUDE.md §Gotchas PR fix(scoring): inject stale_filing_hard before Top-5 rotation (latent Rule-16 fix) — closes #309 #310 no-verbatim-copy lesson).Verification (run locally, not just CI)
python -m py_compileOK ·ruff check .clean · full offline suite 1460 passed / 11 skipped / 0 failures (OSAP files env-gated locally, pass on CI).Known follow-up (non-blocking, from review)
continueinvariant (the property that keepslen(exchange_by_ticker) == detail_count). Closing it needs the lightweightrun_weekly_computeorchestrator harness that the suite defers elsewhere (thetest_wall_clock_schemaTODOs) — appropriately a separate effort, not this PR.Doc lockstep: CLAUDE.md + AGENTS.md in-flight entries flipped PR-A1 → PR-A2; full entry in
PHASE_STATUS_INFLIGHT.md.https://claude.ai/code/session_0148EoMmL6zakDWqHXjqQ9yq
Generated by Claude Code