150 Commits

Author SHA1 Message Date
Rene Fichtmueller
3cbfabbb38 feat(procurement): availability why-attribution + per-SKU price momentum (1.6T: 2 suppliers, +13.7% same-SKU, 0% stock) 2026-06-11 10:22:30 +00:00
Rene Fichtmueller
5d69f0160c feat(procurement): data-grounded supply-availability signal per speed tier (1.6T scarce/800G moderate/400G abundant from real supplier+stock data) 2026-06-11 09:19:57 +00:00
Rene Fichtmueller
de40c65b01 feat(switch-compat): hard verification gate — only manufacturer-verified switches show compatibility
A switch presents transceiver compatibility ONLY if ports_verified=true (its port
config confirmed against the manufacturer datasheet). Unverified switches return
NO suggestions rather than potentially-wrong data. New columns: ports_verified,
ports_verified_source, ports_verified_at. Verified so far against datasheets:
HPE Aruba CX 10000-48Y6C, NVIDIA SN3700 (corrected 100G->200G QSFP56), SN4700,
SN5400, SN5600. 262 switches still pending datasheet verification.
2026-06-11 08:59:01 +00:00
Rene Fichtmueller
2dc21ee0aa fix(switch-compat): parse embedded port speed for chassis switches
Chassis switches use ports_config keys like 'max_per_slot_100G_QSFP28' (speed in
the middle), not just '100G_QSFP28'. The '^[0-9.]+G' anchor failed -> port_speed
NULL -> 0 suggestions (e.g. Cisco 8818 router). Now extracts the speed token
wherever it sits before the cage. Cisco 8818: 0 -> 55, all Cisco-codeable, max 400G.
2026-06-11 06:57:42 +00:00
Rene Fichtmueller
3bec30bad3 fix(switch-compat): require Flexoptix coding for the switch vendor (actually runs)
Physical fit alone is not real compatibility — a module that seats in the cage
still won't run unless Flexoptix can code it for the switch's platform. Added a
coding requirement: each suggestion must have an fx_compatibilities entry for the
switch's mapped vendor (HPE/Aruba->aruba, Cisco->cisco, NVIDIA->mellanox, etc.;
whitebox/unmapped -> MSA Standard fallback).

CX 10000-48Y6C: 629 physically-fitting -> 283 actually-codeable-for-Aruba. All
283 verified to carry an Aruba coding. Every suggestion is now catalog-confirmed,
datasheet-accurate, physically fitting AND guaranteed codeable to run in the switch.
2026-06-11 06:55:48 +00:00
Rene Fichtmueller
7f13144c53 fix(switch-compat): only suggest catalog-confirmed Flexoptix parts (fx_specifications)
~107 parts were misattributed to the Flexoptix vendor but do not exist in the
live Flexoptix catalog (FX uses dot-SKUs like S.1606.28.KD; these use dash-SKUs
like FOT-AX-200G). They polluted 'BEI FLEXOPTIX BESTELLEN' with non-orderable
phantom parts carrying name-guessed specs. Now require fx_specifications IS NOT
NULL — every suggestion is confirmed in Flexoptix's API with authoritative
datasheet specs. CX 10000-48Y6C: 801 -> 630 suggestions, all catalog-confirmed,
0 physically impossible, 0 phantoms.
2026-06-11 05:36:44 +00:00
Rene Fichtmueller
2b7d5c7037 fix(switch-compat): physically validate Flexoptix suggestions by port speed + cage mechanics
getFlexoptixSuggestions matched ONLY by form factor, discarding the speed encoded
in each ports_config key (e.g. '100G_QSFP28'). Corrupt transceiver speed_gbps
values (400G/200G/128G/100000G mislabeled as QSFP28) leaked through, so a 100G
switch showed impossible '400G QSFP28' / '100T QSFP28' suggestions.

Now parses (speed, form_factor) from each port key and requires every suggested
module to (a) mechanically seat in the cage — precise port-FF -> accepted-module-FF
map, a QSFP28 cage takes QSFP+/28/56 but never QSFP-DD — and (b) have
speed_gbps <= the port's speed. CX 10000-48Y6C (25G SFP28 + 100G QSFP28) now
returns only valid <=25G SFP / <=100G QSFP modules; 0 physically impossible
entries (was 4 garbage groups). Belt-and-suspenders: even with corrupt speed data,
nothing oversized can reach a customer-facing suggestion.
2026-06-10 22:39:24 +00:00
Rene Fichtmueller
8c6df1028d merge: reconcile Erik-deployed fixes with Gitea feature branch (origin/main)
Merges 28 Gitea commits (Transceiver Academy, dashboard features A-P, equivalence
matchers OPN/spec, Abverkauf velocity engine, Flexoptix detail sync, SQL 111-118,
MCP equivalences tool, training data) with 22 Erik-local commits (price chart,
fmtSpd, supply-squeeze per-SKU fix, research-robot actions, NADDOD warehouse,
FS competitor stock, reorder bloat fix, flexoptix empty-token fix, vendor
reliability, blog WireGuard failover).

Only 2 files changed on both sides; ort auto-merged both cleanly. Manually
resolved a resulting duplicate GET /api/hype-cycle/market-signals: kept the
Erik handler (technologies+marketSignalScore+drivers+globalContext, matches the
merged dashboard), removed the Gitea Multi-source variant (preserved in history).

All 3 packages build with 0 TS errors. Safety: branch erik-pre-reconcile-20260607,
bundle _RECON_full-backup-20260607.bundle (also on Fearghas), bulk-price WIP in
stash@{0}, untracked SQL backed up to _RECON_untracked_sql_20260607/.
2026-06-07 05:01:32 +00:00
Rene Fichtmueller
a9f95fc552 feat(research-robot): actionable recommendations + dispatch/pause/resume buttons
The Research Robot panel showed only an LLM assessment (info, no action). Now:

API (research-robot.ts):
- GET enriches response with recommendations[] computed from live pgboss state:
  classifies each persistently-failing job (auth/401, network, no-handler, other)
  into severity + concrete advice + offered actions.
- POST /action {action,job}: dispatch (enqueue one run), pause (remove from
  schedule with backup to research_robot_paused_schedules), resume (restore).
  All validated against the pgboss.queue whitelist.

Dashboard:
- Renders each recommendation as a card with severity colour, cause, last error,
  and action buttons (Jetzt auslösen / Pausieren / Fortsetzen / Token-Anleitung).
- Verified: sync:flexoptix-catalog -> critical auth (HTTP 401), offers
  token-help + pause. Dispatch/pause/resume roundtrip tested green.
2026-06-06 16:53:54 +00:00
Rene Fichtmueller
0cf607040f fix(supply-squeeze): per-SKU paired price comparison eliminates catalog-composition bias
The 30d-vs-60d price momentum aggregated AVG/median across whatever SKUs
happened to be in a speed/form-factor bucket each period. New expensive SKUs
entering the catalog (NVIDIA switches at 30k USD, AOC cables) faked huge jumps
— 400G OSFP showed +151% when matched-SKU reality was 0%.

Now: compute per-transceiver median price in each period, keep only SKUs present
in BOTH periods (>=2 obs each), report the median of per-SKU pct deltas. Also
excludes non-transceiver form factors, AOC/DAC cables, switch SKUs, price>15k,
and anomalous observations. Result: 400G OSFP +151%->0%, signals 21->8, and the
ones that remain (NVIDIA MFA7U10 +84% same-SKU) are genuine price moves.
2026-06-06 16:48:15 +00:00
Rene Fichtmueller
9bf7da3fda feat(stock): FS.COM competitor stock by technology in Sales Velocity table
Adds /api/stock/competitor-by-tech endpoint aggregating warehouse_de_qty +
warehouse_global_qty from stock_observations for public competitors (FS.COM
etc.) per technology class. Dashboard velocity table gets two new columns
FS.COM DE + FS.COM Global with traffic-light coloring vs. monthly demand.
2026-06-05 23:06:13 +00:00
Rene Fichtmueller
842a85120b fix(price-movers): dedup by part_number, median price, CV-filter for tier noise
Group by part_number instead of transceiver_id (eliminates OEM duplicate rows).
Use PERCENTILE_CONT median instead of AVG to reduce single-outlier impact.
Add CV-filter (stddev/avg <= 0.35 over 2x window) to exclude high-variance
sources like Mouser quantity-tier pricing that produces artificial swings.
2026-06-05 21:23:20 +00:00
Rene Fichtmueller
c6e79e9967 feat(vendors): add /reliability endpoint (per-vendor freshness/frequency/coverage scores from real data) 2026-06-04 21:08:08 +00:00
Rene Fichtmueller
f067c0999d fix(vendors): reach /market-share + /intelligence (next() fallthrough past /:id) + fix SQL (numeric casts for ROUND division, COUNT(*) not non-existent po.id) 2026-06-04 20:58:12 +00:00
Rene Fichtmueller
b720afc92c feat(hype-cycle): add /market-signals endpoint (data-driven per-tech signal score + drivers + recommendation) 2026-06-04 20:47:30 +00:00
Rene Fichtmueller
b5a961c3bd feat(blog): automatic primary->fallback failover for Ollama endpoint
Blog LLM client probes BLOG_OLLAMA_URL (primary, WireGuard tunnel to Mac
Studio loopback Ollama) and falls back to BLOG_OLLAMA_URL_FALLBACK
(Cloudflare tunnel) when the primary transport is unreachable. Re-probed
at startup and every 60s; prefers primary when available. Both tunnels
terminate on the Mac loopback over independent transports, so the blog
keeps reaching fo-blog regardless of which transport drops.
2026-06-04 18:28:45 +00:00
Rene Fichtmueller
3577668cf3 feat(blog): route fo-blog LLM to Mac Studio via WireGuard
Blog auto-discovery + generation now use BLOG_OLLAMA_URL (-> Mac Studio
192.168.178.213:11434 over the Erik<->home WireGuard tunnel), falling
back to OLLAMA_URL. Search/embeddings stay on Erik-local OLLAMA_URL
(nomic-embed-text). Fixes blog model not-found after OLLAMA_URL was
repointed to Erik-local for the search fix.
2026-06-04 18:02:01 +00:00
Rene Fichtmueller
b5925bc264 Merge remote-tracking branch 'origin/erik-live-2026-06-04' into reconcile-2026-06-04
# Conflicts:
#	CHANGELOG_PENDING.md
#	packages/api/src/index.ts
#	packages/api/src/llm/client.ts
#	packages/api/src/routes/blog.ts
#	packages/api/src/routes/bulk-price.ts
#	packages/api/src/routes/kb.ts
#	packages/api/src/routes/price-matrix.ts
#	packages/api/src/routes/procurement.ts
#	packages/api/src/routes/stock.ts
#	packages/api/src/routes/vendor-reliability.ts
#	packages/api/src/routes/vendors.ts
#	packages/dashboard/index.html
2026-06-04 13:56:42 +00:00
Rene Fichtmueller
172ec324f2 snapshot: Erik live-deployed state 2026-06-04 (capture for source reconciliation) 2026-06-04 12:46:49 +00:00
Rene Fichtmueller
aa6ce9cc26 fix(api): switch-compat vendor join + min_price aggregate + win-loss form_factor ambiguity 2026-06-04 10:38:15 +00:00
Rene Fichtmueller
f2dad45c7c fix(api): part-number ILIKE search + verified-first catalog ordering + FTS-primary product search 2026-06-04 10:14:19 +00:00
Rene Fichtmueller
d6da7aa94c fix(api): part-number ILIKE search + verified-first catalog ordering + FTS-primary product search 2026-06-04 10:11:37 +00:00
Rene Fichtmueller
adfb590ad2 feat: Transceiver Academy — full API-backed customer & employee training platform
Replaces the old LLM-training inline data module with a proper interactive
training platform for annual employee onboarding and customer education.

Content (236 KB of structured training data):
- 5 categories: Standards, Form Factors, Switches & Compatibility,
  Fiber & Infrastructure, Testing & Buying
- 22 detailed lessons with bilingual content (EN + DE)
- 74 quiz questions with explanations in both languages
- Lesson types: beginner / intermediate / advanced
- Content blocks: paragraphs, tables, callouts, code blocks, formulas, lists

API route (GET /api/training/*):
- /categories — all 5 categories with lesson/quiz counts
- /lessons?category= — lesson metadata for category
- /lessons/:id — full lesson content (sections + blocks)
- /quiz?lesson=&category= — quiz questions with bilingual answers
- /stats — aggregate stats
- Public route (no auth token required)

Dashboard (Transceiver Academy UI):
- Language toggle EN/DE (persisted in localStorage)
- Category selector tabs with lesson counts
- Lesson cards with level badge, summary, duration, completion indicator
- Full lesson viewer: renders all block types with bilingual support
- Per-lesson quiz and per-category quiz
- Question-by-question quiz engine with auto-advance, dots progress indicator
- Results screen with grade (A-F), wrong answers + explanations
- Progress tracking in localStorage, global progress bar
- Reset progress button
2026-05-14 22:31:43 +02:00
Rene Fichtmueller
e71b985c52 feat: 10 weitere Dashboard-Features (G–P)
G) SKU Bulk Pricer — POST /api/bulk-price (bis 100 Part Numbers),
   Preistabelle je Vendor, CSV-Export, Not-Found-Liste

H) Side-by-side Comparison — Checkboxes in TX-Tabelle,
   Floating Comparison-Tray (max 4 SKUs), Modal mit Specs +
   Best-Price 7d nebeneinander

I) Vendor Reliability Score — GET /api/vendors/reliability,
   Freshness(40) + Frequency(30) + Coverage(30) = 0–100,
   Progress-Bar-Badge auf Vendor-Cards

J) Price Heat Map — GET /api/price-matrix?ids=,
   Row-normalisierte Farbmatrix SKU×Vendor (grün=günstig/rot=teuer),
   Sticky SKU-Spalte, Best-Price-Spalte

K) Watchlist — localStorage-basiert (/☆ in TX-Tabelle),
   Floating Drawer, live Preis-Update via Einzelabruf

L) PDF / Print Report — window.print() + dediziertes @media print CSS
   (blendet UI-Chrome aus, behält Overview-Content)

M) Global Search Overlay — Cmd+K / Ctrl+K, durchsucht Transceivers
   + KB + News + Documents gleichzeitig, clickbare Direktlinks

N) Saved Filter Presets — localStorage tip_presets, Dropdown +
   💾-Button in TX-Filterzeile, Save/Load/Delete

O) Price Forecast — GET /api/price-forecast/:id (lineare Regression
   90d → 30d Forecast), gestricheltes Overlay auf Price-History-Chart,
   Trend-Label (rising/stable/declining)

P) Technology Radar — SVG Bull's-Eye (Adopt/Trial/Assess/Hold),
   Hype-Cycle-Phasen → Ringe gemappt, Bubbles mit Market-Signal-Score,
   Quadrant-Labels, interaktive Tooltips
2026-05-14 21:39:17 +02:00
Rene Fichtmueller
fb060ee40a feat: 6 neue Dashboard-Features (A–F)
A) Price Movers Alert
   - GET /api/procurement/price-movers?days=N&limit=N
   - CTE cur vs prior period avg, |delta_pct| >= 2%, gainers+losers
   - Procurement tab: period toggle 7d/14d/30d, stats bar, Export CSV

B) Executive Overview Pulse
   - 5 KPI cards in Overview (Buy Signals, Arbitrage Ops, Supply Alerts,
     Price Gainers, Losers) via loadProcurementPulse()
   - Top-Movers mini-table in overview card, all → Procurement tab

C) CSV Export
   - exportMoversCSV() downloads gainers+losers as CSV

D) Vendor Intelligence
   - GET /api/vendors/intelligence: per-vendor 30d stats
     (sku_count, price_obs, avg/min/max price, last_seen)
   - Top-6 banner in Vendors tab

E) Advanced Transceiver Search
   - Speed filter (1G/10G/25G/40G/100G/200G/400G/800G)
   - Fiber type filter (SMF / MMF)
   - Verified-only checkbox
   - All params forwarded to GET /api/transceivers

F) Knowledge Base Browser
   - New KB tab with full-text search (ILIKE question/answer/subcategory)
   - GET /api/kb?q=&category=&limit= (packages/api/src/routes/kb.ts)
   - Category pills, entry cards with severity badge + FF/speed tags
2026-05-14 20:54:40 +02:00
Rene Fichtmueller
bcab2b97af feat: procurement — 5 intelligence sections (A-E)
E  Buy-Now Intel    211k precomputed reorder signals surfaced,
                    filterable by form factor, signal strength bars
A  Arbitrage        59k equivalence pairs + price data, FX vs comp
                    normalized to USD, sorted by savings %
B  Switch Compat    search 429 switches → compatible transceivers
                    with prices; 58k compatibility rows
C  Supply Squeeze   4-signal detector: price momentum (30d vs 60d),
                    hype phase, AI cluster demand, stock pressure
D  Dead Stock       7,297 dead-stock SKUs matched against ascending
                    hype phases (revival candidates)

5 new API endpoints: /api/procurement/reorder-top, /arbitrage,
/switch-compat, /supply-squeeze, /dead-stock-revival
2026-05-14 18:31:07 +02:00
Rene Fichtmueller
4bd16af9a5 feat: data quality panel in Crawler Intelligence tab
GET /api/scrapers/data-quality — 4 parallel queries across 200k+
transceiver_verification_evidence rows. Returns: coverage percentages
(price 62%, image 68%, details 94%, competitor 2%), all 10 evidence
types with counts + avg confidence, 17 robot/scraper contributions,
14-day daily activity time series.

Dashboard: coverage progress bars (color-coded thresholds), evidence
type table, SVG activity sparkline, robot contributions table.
2026-05-14 16:22:25 +02:00
Rene Fichtmueller
10d13633fb feat: dynamic hype cycle + market signal engine + eBay/CapEx panels
6-source composite Market Signal Score (0-100) per transceiver technology.
New GET /api/hype-cycle/market-signals blends: Norton-Bass hype_score,
hyperscaler CapEx YoY (MSFT +68.8%, GOOG +107%, META +46.8%), price
observation activity ratio 30d vs prior 30d, AI cluster transceiver demand,
eBay secondary market sell-through velocity, internal fast-mover trend.
All 6 queries run in parallel via Promise.all().

Recommendation engine maps hype phase × capex boom × speed class →
Buy/Hold/Watch labels with tooltips. Dashboard Hype Cycle table now shows
Market Signal ● LIVE column + Recommendation column. Hyperscaler CapEx
panel + eBay panel added to hype tab. Procurement: new eBay Market section.
Sourcing Hype Cycle replaced hardcoded seed with live price observation data.
2026-05-14 16:17:52 +02:00
Rene Fichtmueller
13fe33eceb feat: procurement — Internal Demand + AI Clusters sections with real data
Two new procurement sub-tabs backed by live database tables:

📦 Internal Demand (flexoptix_internal_demand, 8,585 SKUs):
- Velocity cards: fast_mover (70 SKUs, 53k units/12M), regular, slow, dead stock
- Filterable table with demand_12m, demand_3m, trend %, form factor
- GET /api/procurement/internal-demand — summary + paginated rows

🤖 AI Clusters (ai_cluster_announcements, 396 rows last 30d):
- Live datacenter build announcements with estimated transceiver demand
- Stats: total announcements, MW sum, distinct companies, total ~transceivers
- Filter for entries with transceiver estimates; time range selector
- GET /api/procurement/ai-clusters — data + period stats

Also: replaced misleading DEMO DATA banners on Reorder Signals and ABC
Classification sections with informational notes pointing to real data.
2026-05-14 16:04:11 +02:00
Rene Fichtmueller
ea8be4aea3 feat(tip): equivalences explorer + price history charts + linkedin status + MCP tools
Equivalences Explorer:
- GET /api/equivalences — search 63k cross-brand mappings by part number/vendor
- GET /api/equivalences/transceiver/:id — all equivalences for a specific product
- GET /api/equivalences/stats — active count, unique products, avg confidence (93.9%)
- GET /api/equivalences/top-vendors — top 20 competitor vendors by coverage
- New "Equivalences" tab in dashboard with part-number search, vendor filter,
  quick-click vendor chips, and results table with confidence coloring
- Transceiver detail modal: equivalences panel (Flexoptix alternatives or competitor
  products), clickable rows, confidence percentage, orange highlight for FX products

Price History Charts:
- GET /api/price-history/:id?days=90 — daily min/max/avg per source vendor (392k obs)
- Transceiver detail modal: SVG sparkline chart per vendor, legend with latest prices,
  range summary — loads async without blocking the modal

LinkedIn Distribution Status:
- GET /api/blog/linkedin/history — from blog_linkedin_distribution table
- Blog tab: LinkedIn status panel showing DRY_RUN badge, posted/dry_run/skipped/failed
  stats, distribution history table with URN link to live posts

MCP Server — 2 new tools:
- find_equivalences: search 63k+ verified cross-brand mappings with confidence filter
- get_price_history: 392k+ observations, daily series, per-vendor analysis, cheapest source
2026-05-14 15:54:01 +02:00
Rene Fichtmueller
67310c8fe7 fix(blog): SPA-aware URL blog generation + dynamic generated_by
- fetchUrlContent() now extracts OG/meta tags (og:title, og:description,
  name="description", og:site_name) as fallback content for JS-rendered SPAs
- Returns spaDetected=true when body text < 300 chars after stripping scripts
- from-url endpoint skips gatherBlogData() product injection when SPA detected,
  preventing fo-blog-v10 from defaulting to optical networking domain
- additionalContext now includes SPA warning instructing LLM not to default
  to optical transceiver topics unless the page is actually about that
- generated_by in pipeline UPDATE query now uses active model name instead of
  hardcoded 'fo-blog-engine-v7' (reads getLlmProvider().ollamaModel)
- Dashboard shows SPA warning toast when spa_detected=true in response
- Response now includes spa_detected field for client awareness
2026-05-14 12:29:17 +02:00
Rene Fichtmueller
e0f9656684 feat: Blog Engine — generate from URL (link → BlogLLM → article)
New POST /api/blog/from-url endpoint:
- Accepts url + topic in request body
- Fetches page server-side (no CORS, 20s timeout, redirect-follow)
- Strips script/style/nav/footer/svg; extracts readable text (~5000 chars)
- Extracts page title from <title> or <h1>
- Passes extracted content as structured additional_context to the
  existing 16-step FO blog pipeline (same as manual generation)
- Returns immediately; LLM pipeline runs async
- Validated: smoke test fetched flexoptix.net/en/blog/, 5040 chars,
  pipeline launched with llm_enhancing=true

New "🔗 Blog aus URL generieren" panel in dashboard:
- URL input (Enter key triggers generation)
- Blog-Typ dropdown (same 8 types as manual panel)
- Button shows loading state " Fetching…" during API call
- Status line shows extracted char count after success
- Reuses pollBlogLlm() for step-by-step progress polling
- Inline status field for error display without toast spam
2026-05-14 00:55:35 +02:00
Rene Fichtmueller
9b8b03e783 feat: Flexoptix section — speed formatting + Lagerbestand display
Speed display: fix raw Gbps decimals → formatted labels
- 1600.00G → 1.6T (≥1000 Gbps converted to T)
- 400G → 400G (clean integer, no trailing .00)
- Helper function fmtSpeed() added in dashboard JS

Lagerbestand: add stock availability per transceiver
- getFlexoptixSuggestions() extended with LEFT JOIN LATERAL on
  stock_observations (latest row per transceiver)
- Returns warehouse_de_qty, warehouse_global_qty, backorder_qty,
  backorder_estimated_date
- Dashboard renders color-coded badges per row:
    green  = DE-Lager quantity
    blue   = Global-Lager quantity
    yellow = Zulauf with estimated delivery date if available
- Badges hidden when all quantities are null/zero (graceful fallback)
2026-05-14 00:52:21 +02:00
Rene Fichtmueller
de179c4c7c fix: remove DEMO labels from real stock data; fix switch Flexoptix suggestions; enrich Hot Topics LLM context
Stock dashboard (index.html):
- Replace all [DEMO]/demo badges on warehouse data with "FS.com" source labels
  (data was always real scraper data, never demo in the DB)
- Update subtitle: "Scraper-Lagermengen: DEMO DATA" → "Wettbewerber-Marktdaten"
- "Recently Restocked" badge: DEMO DATA → SCRAPER DATA

Switch detail (queries.ts):
- Fix getFlexoptixSuggestions: wavelength_nm → wavelength_tx_nm,
  price_verified_usd → street_price_usd (column mismatch with live schema)
- DS5000 and other OSFP switches now show all 62 Flexoptix OSFP transceivers
  with direct shop links in the detail modal

Hot Topics (hot-topics.ts):
- NOG Talks + News Article clusters now fetch summary/mentioned_vendors/
  mentioned_products/mentioned_standards from news_articles table
- description field builds bullet-point list per article with summaries,
  key vendors/standards (vs. 3 bare titles joined with "|" before)
- buildTopicBriefing() rewritten as structured LLM document with sections:
  Market Signals (bullets), Recommended Angle, Market Context (buy signal,
  technologies, impact horizon), Writing Instructions (600-900 words,
  actionable, opinionated, no generic summaries)
2026-05-14 00:33:45 +02:00
Rene Fichtmueller
0d7a92e749 feat: Abverkauf velocity engine — sql/118 + analyzer + API endpoints
- sql/118-stock-velocity.sql: new stock_velocity (UPSERT per tx×vendor)
  and stock_velocity_events tables with TimescaleDB-compatible indexes
- stock-velocity-analyzer.ts: computes sell-through from stock_observations
  time-series; detects sold/zulauf/data_gap events, trims top-10% outliers,
  predicts stockout date, assigns high/medium/low/insufficient confidence
- scheduler.ts: analyze:stock:velocity job at 04:30/12:30/20:30 UTC
- stock.ts: GET /api/stock/velocity (paginated, filterable by vendor/confidence/
  stockout_days) + GET /api/stock/velocity/:id (per-product with event history)
- First run: 208 products, 979 sell events, 2811 Zulauf events written
2026-05-14 00:24:58 +02:00
Rene Fichtmueller
048bf0dcf2 feat: add Codex task for Flexoptix reference matching overhaul
CODEX-TASK-flexoptix-reference-matching.md — comprehensive plan to fix
zero-match gap for ATGBICS/NADDOD/10Gtek/ShopFiber24 (8.260+ products
with 0 Flexoptix equivalences).

Root cause: 30-day price_observation window excludes vendors whose
scrapers ran >30 days ago. Solution: catalog-reconcile robot (full
bulk match, no time limit), form_factor normalization (SQL 108),
30→90 day window fix in nightly matcher, on-demand API endpoint.

Expected: coverage from 22% → 45-60% after one reconcile run.
2026-05-13 16:51:53 +02:00
Rene Fichtmueller
a0657ee565 fix: filter TIP hot topics quality 2026-05-10 15:54:38 +02:00
Rene Fichtmueller
5eb1b07183 fix: close stale TIP manual review queue 2026-05-10 10:23:07 +02:00
Rene Fichtmueller
cf0e471fa4 feat: close TIP research resolution states 2026-05-10 10:13:09 +02:00
Rene Fichtmueller
10af2ca244 fix: generated_by tag — v6-length-fix → v7 2026-05-10 09:55:39 +02:00
Rene Fichtmueller
b58f7cee41 feat: resolve OEM price status and part details 2026-05-10 01:16:49 +02:00
Rene Fichtmueller
650de6ba9a feat: add verification evidence state model 2026-05-09 23:06:21 +02:00
Rene Fichtmueller
1af4f090f7 fix: harden TIP verification cleanup 2026-05-09 22:16:29 +02:00
Rene Fichtmueller
a43e572946 fix: advance TIP product verification robots 2026-05-09 20:19:19 +02:00
Rene Fichtmueller
fc18b00157 fix: verify copper cable semantics 2026-05-09 16:55:50 +02:00
Rene Fichtmueller
61acccf5df fix: require strict comparable transceiver evidence 2026-05-09 16:02:49 +02:00
Rene Fichtmueller
43b7250180 fix: automate equivalence research review queue 2026-05-09 07:48:11 +02:00
Rene Fichtmueller
a1a525b332 chore: sync API routes, dashboard hot-topics, MCP server, scraper package, scripts 2026-05-06 23:39:04 +02:00
Rene Fichtmueller
270bd12382 feat(dashboard): clickable LLM model selector — switch blog engine at runtime
- client.ts: BLOG_LLM_PROVIDER/OLLAMA_LLM_MODEL as mutable state (setLlmProvider/
  getLlmProvider). Reads blog-llm-settings.json on startup for persistence.
  All generate()/checkHealth()/chat() calls use dynamic provider() + llmModel()
  — no restart required for switches.

- blog.ts: POST /api/blog/llm/switch endpoint — validates provider, calls
  setLlmProvider(), writes settings file, returns previous+active state.

- index.html: all 4 model cards now clickable (cursor:pointer, hover fade).
  switchBlogLlm(provider, model) — disables cards during switch, shows
  green/red feedback toast, auto-refreshes status. SSH instruction removed.
2026-04-29 01:15:45 +02:00
Rene Fichtmueller
b5decc517f fix: hard-cap blog generation to 800-1100 words
LLM_OPTS.maxTokens 8192 → 1600, LLM_REFINE 6144 → 1800,
Step 4 master draft 8192 → 1600. Added explicit word-count
constraint to STEP4_MASTER_DRAFT prompt: HARD LIMIT 800-1100 words.

Root cause: no token ceiling → fo-blog-v6 produced 4000-5000w articles.
Generated-by label updated to fo-blog-engine-v6-length-fix.
2026-04-28 22:45:48 +02:00