Commit Graph

10 Commits

Author SHA1 Message Date
Kunthawat Greethong
2b7a065ae5 fix(ui,health): move source-health log to bottom of page; one row per source (latest)
- Health panel relocated below Backtest (last section) per owner — it's
  operational detail, not an investment view.
- scheduler._load_source_health now returns only the LATEST entry per source
  key (was returning the full refresh history, so siamchart_vintages and
  price_snapshot appeared as 2 rows). Verified: 11 sources / 11 unique rows.
- frontend v-for drops slice(0,20) and keys by source key.

Verified in-browser: #health is the last section; 11 unique source rows.
2026-08-31 17:03:07 +07:00
Kunthawat Greethong
053b94b45f fix(ui): eliminate table/grid overflow breaking the frame at every width
Two root causes of tables and panels spilling past the window frame:

1. Global 'table { min-width: 850px }' forced EVERY table (source/score/modal/
   backtest) to 850px regardless of container -> now min-width:0 so tables
   shrink to 100%; only .factor-table (stock board, inside .table-wrap)
   keeps its 850px and scrolls. Small tables get table-layout:fixed +
   overflow-wrap on mobile so long content wraps instead of pushing out.

2. Grid/flex tracks lacked minmax(0,1fr) / min-width:0, so wide grid items
   (KPI numbers, theme cards) pushed the whole row past the viewport at
   768-1040px (doc overflow 208px). Fixed: all grid-template-columns use
   minmax(0,1fr); .content is now flex:1 1 auto + min-width:0; KPI/theme/bt
   cards get min-width:0 + overflow-wrap.

Verified programmatically in-browser: document overflow = 0 at 320/360/500/
600/720/760/768/820/900/1040/1200/1440px; score-table + source-table over=0
at all widths (incl inside the per-source modal). Board scrolls in .table-wrap
as designed. Backend suite 369 green (CSS-only change).
2026-08-30 09:10:21 +07:00
Kunthawat Greethong
3010ab287f fix(ui): show theme weighted-average verification in per-source modal
After reviewer suggestion: per theme, display sum(contribution)/sum(|weight|) =
theme surprise so the owner can confirm the source audit matches the real score.
2026-08-29 12:18:40 +07:00
Kunthawat Greethong
7f175e5a05 feat(scoring): flexible source fallback (no board crash) + per-source calc audit (Q2, Q3)
Q2 flexible scoring: _fetch_with_cache now degrades instead of raising
DashboardError — a source that fails with no cached value returns {} so the
theme scorer drops that source's factors; a previously-good value is kept as
stale by the daily cache. Verified: all-sources-down still builds 13 themes.

Q3 per-source audit: new themes.factor_source_breakdown(fetched, theme) shows
per factor source/raw/normalized/weight/contribution; dashboard exposes
fetch_data + factor_sources; per-symbol modal renders symbolDetail.factor_sources
(e.g. retail: te_thailand ยอดขายปลีก -14.5 -> -1.0 x 0.7 = -0.7).

Suite 369 green; independent review passed: true.
Q1 (HAR for deferred sources) spike recorded: method works, REIC needs deeper
interaction; NBTC 403 likely unbpassable without a session.
2026-08-29 12:15:54 +07:00
Kunthawat Greethong
12b34929d7 feat(factor): add energy_irpc (IRPC net margin) as 2nd Thai refiner signal
- new energy_irpc collector parsing IRPC performance-highlights table
  (net profit/EBITDA/ROE margins, latest period 3M26: +10.27%)
- factor energy_irpc_net_margin (sign +1) wired into refining_energy/
  exploration/utilities, extending the energy theme beyond TOP
- scheduler job + dashboard fetch + sources table row (now 9 sources)
- tests: parse (incl paren-negatives), value-key resolution, direction;
  suite 368 OK. Independent review passed: true
- Phase B feasibility: REIC/EPPO/NBTC/PTTEP are JS-rendered or anti-bot
  (recorded deferred in plan); IRPC was the clean server-rendered win
2026-08-29 11:13:17 +07:00
Kunthawat Greethong
9516a7a8e8 fix(ui): theme-card reads for new sources + padding/undefined-css-var fixes
- define missing design tokens (--card/--foreground/--accent/--font/--text-2)
  that theme/modal components referenced but :root never declared (they rendered
  transparent/wrong color)
- zero section-panel padding so .signal-header is the single top-spacing source
  (was double 22px+22px on theme/lineage/health/sim/backtest panels)
- theme cards now surface the new source reads (banks rate, retail sales YoY,
  nonbank household debt, property prices, telecom business confidence)
2026-08-29 09:19:01 +07:00
Kunthawat Greethong
7a3cfac19a feat(ui): rename Simulation→Suggestion, remove forward-test mode entirely (backend routes/store + frontend panel/option), fix stock-list overflow in allocation display 2026-08-29 01:57:13 +07:00
Kunthawat Greethong
14b2aeff7c feat(scheduler): per-source cadence + source-health log with failure diagnosis + UI copy 2026-08-28 11:41:48 +07:00
Kunthawat Greethong
d73a58b3d1 [verified] Task 7: frontend PIT readiness gate + event-driven backtest report 2026-08-28 10:32:10 +07:00
Kunthawat Greethong
f9b8cd10b2 feat(deploy): single-container Docker packaging (nginx + Flask + prebuilt SPA)
Add self-contained Docker deployment for EasyPanel / docker-compose:

- Dockerfile: python:3.11-slim + nginx. Serves the PREBUILT Vue SPA
  (frontend/dist, committed) via nginx and reverse-proxies /api to the Flask
  backend on 127.0.0.1:5000. No node/npm in the image (avoids Vite/npm
  flakiness in Docker builds). VOLUME /app/backend/data for persistence
  (factor vintages, dividend ledger, forward runs, prices). HEALTHCHECK hits
  /api/v1/dashboard/summary. Exposes :80.
- deploy/nginx.conf: SPA fallback + /api proxy to 127.0.0.1:5000 + gzip.
- deploy/entrypoint.sh: starts Flask (HOST=0.0.0.0:5000) + nginx foreground,
  forwards signals.
- docker-compose.yml: single service 'set50', port 8080:80, mounts
  ./backend/data for persistence, healthcheck.
- .dockerignore excludes .git/.venv/backend/data/node_modules/docs.
- .gitignore now tracks frontend/dist/ (prebuilt bundle required by the
  image); backend/data stays untracked.
- Backend runtime verified: test_client GET /api/v1/dashboard/summary=200
  (the HEALTHCHECK path). entrypoint sh -n, compose YAML parse, and all
  Dockerfile-referenced files exist. NOTE: no local docker here, so the
  image itself was not built — that happens on EasyPanel.
2026-08-27 13:26:58 +07:00