From f5a338fc4eee5ee1d968303a2dc78dd69b6b6418 Mon Sep 17 00:00:00 2001 From: Kazuma Date: Thu, 4 Jun 2026 11:06:30 -0400 Subject: [PATCH] phase-2: extract shared utils --- CLAUDE.md | 42 ++++--- bin/finance.js | 10 +- bin/screen.js | 6 +- bin/server.js | 2 +- {src => server}/analyst/CatalystAnalyst.js | 0 {src => server}/analyst/LLMAnalyst.js | 0 {src => server}/calls/MarketCallStore.js | 0 {src => server}/config/ScoringConfig.js | 0 {src => server}/config/constants.js | 0 .../finance/PersonalFinanceAnalyzer.js | 0 {src => server}/finance/PortfolioAdvisor.js | 0 .../finance/clients/SimpleFINClient.js | 0 {src => server}/market/BenchmarkProvider.js | 0 {src => server}/market/MarketRegime.js | 0 {src => server}/market/YahooClient.js | 0 {src => server}/reporters/FinanceReporter.js | 0 {src => server}/reporters/HtmlReporter.js | 0 {src => server}/screener/Chunker.js | 0 {src => server}/screener/DataMapper.js | 0 {src => server}/screener/RuleMerger.js | 0 {src => server}/screener/ScreenerEngine.js | 0 {src => server}/screener/assets/Asset.js | 0 {src => server}/screener/assets/Bond.js | 0 {src => server}/screener/assets/Etf.js | 0 {src => server}/screener/assets/Stock.js | 0 .../screener/scorers/BondScorer.js | 0 {src => server}/screener/scorers/EtfScorer.js | 0 .../screener/scorers/StockScorer.js | 0 {src => server}/server/app.js | 3 +- {src => server}/server/routes/calls.js | 3 +- {src => server}/server/routes/finance.js | 3 +- {src => server}/server/routes/screener.js | 3 +- server/server/utils/logger.js | 13 +++ tests/BondScorer.test.js | 2 +- tests/DataMapper.test.js | 2 +- tests/EtfScorer.test.js | 2 +- tests/MarketRegime.test.js | 4 +- tests/PortfolioAdvisor.test.js | 4 +- tests/RuleMerger.test.js | 4 +- tests/ScoringConfig.test.js | 2 +- tests/StockScorer.test.js | 2 +- ui/package-lock.json | 104 +++++++++++++++++ ui/package.json | 2 + ui/src/lib/MarketContext.svelte | 5 +- ui/src/lib/utils.ts | 105 ++++++++++++++++++ ui/src/routes/+page.svelte | 26 +---- ui/src/routes/portfolio/+page.svelte | 45 ++------ ui/src/routes/safe-buys/+page.svelte | 17 +-- ui/tsconfig.json | 8 ++ 49 files changed, 299 insertions(+), 120 deletions(-) rename {src => server}/analyst/CatalystAnalyst.js (100%) rename {src => server}/analyst/LLMAnalyst.js (100%) rename {src => server}/calls/MarketCallStore.js (100%) rename {src => server}/config/ScoringConfig.js (100%) rename {src => server}/config/constants.js (100%) rename {src => server}/finance/PersonalFinanceAnalyzer.js (100%) rename {src => server}/finance/PortfolioAdvisor.js (100%) rename {src => server}/finance/clients/SimpleFINClient.js (100%) rename {src => server}/market/BenchmarkProvider.js (100%) rename {src => server}/market/MarketRegime.js (100%) rename {src => server}/market/YahooClient.js (100%) rename {src => server}/reporters/FinanceReporter.js (100%) rename {src => server}/reporters/HtmlReporter.js (100%) rename {src => server}/screener/Chunker.js (100%) rename {src => server}/screener/DataMapper.js (100%) rename {src => server}/screener/RuleMerger.js (100%) rename {src => server}/screener/ScreenerEngine.js (100%) rename {src => server}/screener/assets/Asset.js (100%) rename {src => server}/screener/assets/Bond.js (100%) rename {src => server}/screener/assets/Etf.js (100%) rename {src => server}/screener/assets/Stock.js (100%) rename {src => server}/screener/scorers/BondScorer.js (100%) rename {src => server}/screener/scorers/EtfScorer.js (100%) rename {src => server}/screener/scorers/StockScorer.js (100%) rename {src => server}/server/app.js (96%) rename {src => server}/server/routes/calls.js (98%) rename {src => server}/server/routes/finance.js (98%) rename {src => server}/server/routes/screener.js (96%) create mode 100644 server/server/utils/logger.js create mode 100644 ui/src/lib/utils.ts create mode 100644 ui/tsconfig.json diff --git a/CLAUDE.md b/CLAUDE.md index 1927fe2..06f22ed 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -32,7 +32,7 @@ npm start -- AAPL MSFT VOO # CLI: specific tickers npm run finance # CLI: portfolio advice + SimpleFIN → finance-report.html npm test # run all unit tests (node:test, zero external deps) npm run test:watch # watch mode — uses verbose spec reporter -npm run format # format all src/bin/tests with Prettier +npm run format # format all server/bin/tests with Prettier npm run format:check # check formatting without writing (used in CI/pre-commit) npm run ui:install # install UI dependencies (ui/ subdirectory) ``` @@ -56,7 +56,7 @@ scripts/ prompts/ catalyst-analysis.md ← daily catalyst analysis playbook (LLM prompt + workflow) -src/ +server/ config/ ScoringConfig.js ← CREDIT_RATING_SCALE + ScoringRules (single source of truth) constants.js ← SIGNAL, ASSET_TYPE, SECTOR, SCORE_MODE, REGIME, SIGNAL_ORDER @@ -199,7 +199,7 @@ CORS is configured for `CLIENT_ORIGIN` env var (default `http://localhost:5173`) ## ScoringConfig Key Values -`src/config/ScoringConfig.js` — single source of truth for all gates, weights, thresholds. +`server/config/ScoringConfig.js` — single source of truth for all gates, weights, thresholds. **STOCK base gates (Fundamental mode):** - `maxPERatio: 15` — Graham's actual rule (trailing P/E) @@ -234,7 +234,7 @@ CORS is configured for `CLIENT_ORIGIN` env var (default `http://localhost:5173`) ## MarketRegime (INFLATED overrides) -`src/market/MarketRegime.js` derives gate overrides from live benchmarks and current rate regime: +`server/market/MarketRegime.js` derives gate overrides from live benchmarks and current rate regime: | Gate | Formula (NORMAL rates) | Formula (HIGH rates) | |---|---|---| @@ -365,10 +365,10 @@ Test output: silent on pass, shows only failures + one summary line (`scripts/su - Asset `type` (uppercased) is the routing key across DataMapper, asset classes, `SCORERS` map, and ScoringRules. - Prefer adjusting `ScoringConfig` or `MarketRegime` over hardcoding numbers in scorers. - BenchmarkProvider caches for 1 hour — restart the server to force a fresh fetch. -- All entry points live in `bin/`. Do not add logic to entry points — they call into `src/`. -- `bin/server.js` starts Fastify; `src/server/` contains all route logic. -- **Never** call `process.exit()` inside `src/` — only `bin/` may do that. -- Class instances don't survive `JSON.stringify`. Call `getDisplayMetrics()` server-side before returning from API routes (see `src/server/routes/screener.js` `serializeAssets()`). +- All entry points live in `bin/`. Do not add logic to entry points — they call into `server/`. +- `bin/server.js` starts Fastify; `server/server/` contains all route logic. +- **Never** call `process.exit()` inside `server/` — only `bin/` may do that. +- Class instances don't survive `JSON.stringify`. Call `getDisplayMetrics()` server-side before returning from API routes (see `server/server/routes/screener.js` `serializeAssets()`). --- @@ -381,7 +381,7 @@ All items completed. Additional features delivered alongside cleanup: **Cleanup done:** - Deleted root-level `finance.js`, `import-portfolio.js`, `markdown.md` -- Deleted `src/server/routes/analyze.js` (orphaned route file) +- Deleted `server/server/routes/analyze.js` (orphaned route file) - Removed dead `analysis` state, `analysisOpen` state, and "🤖 AI Market Analysis" panel from `+page.svelte` - Fixed `.gitignore` — `portfolio.json`, `market-calls.json`, `.env` are now excluded from git @@ -398,13 +398,19 @@ All items completed. Additional features delivered alongside cleanup: **Pending (deferred to later):** - LLM Analysis button on portfolio page (analyse holdings against current news) -### Phase 2 — Extract Shared Utilities -- Create `ui/src/lib/utils.ts` with all pure functions currently duplicated across pages: `sigOrd`, `sorted`, `verdictShort`, `vClass`, `fmtPE`, `fmt`, `fmtShort`, `glClass` -- Create `src/server/utils/logger.js` with shared `noopLogger` constant (currently copy-pasted in `screener.js` and `app.js`) +### Phase 2 — Extract Shared Utilities ✅ COMPLETE -### Phase 3 — Rename `src/` → `server/` -- Rename the directory and update all import paths in `bin/`, internal routes, and `CLAUDE.md` -- Makes the API layer unambiguous — `src/` conventionally implies "all project source" +**Done:** +- Created `ui/src/lib/utils.ts` — typed shared pure functions: `sigOrd`, `sorted`, `verdictShort`, `vClass`, `fmtPE`, `fmt`, `fmtShort`, `glClass`, `advClass`. Exports `Signal` type. +- Created `server/server/utils/logger.js` — shared `noopLogger` constant, imported by `screener.js`, `app.js`, `finance.js`, and `calls.js` +- Added TypeScript support to `ui/` — `tsconfig.json` extending SvelteKit's generated config, `typescript` and `svelte-check` added as dev dependencies +- All three pages (`+page.svelte`, `safe-buys/+page.svelte`, `portfolio/+page.svelte`) now import from `$lib/utils.js` instead of duplicating logic + +### Phase 3 — Rename `src/` → `server/` ✅ COMPLETE + +**Done:** +- Renamed `src/` to `server/` — `src/server/` is now `server/server/` +- Updated all import paths in `bin/`, `tests/`, and `CLAUDE.md` ### Phase 4 — SCSS Migration Replace per-component `