transceiver-db/CHANGELOG_PENDING.md

299 lines
82 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# TIP Changelog
Format: `{"d":"YYYY-MM-DD","t":"TYPE","m":"Description"}`
{"d":"2026-05-14","t":"FEAT","m":"Equivalences Explorer: new dashboard tab '🔀 Equivalences' — search 63,362 cross-brand mappings (46 vendors, 7,516 competitor products → 846 Flexoptix alternatives, Ø 93.9% confidence). APIs: GET /api/equivalences (search), /api/equivalences/transceiver/:id (per-product), /api/equivalences/stats, /api/equivalences/top-vendors. Transceiver detail modal now shows equivalences panel (FX alternatives or competitor products) + SVG price history sparklines (30-day, per source vendor) from 392k+ price observations."}
{"d":"2026-05-14","t":"FEAT","m":"LinkedIn Distribution Status: Blog tab shows DRY_RUN badge, posted/dry_run/skipped/failed counters, history table with live URN links. GET /api/blog/linkedin/history reads blog_linkedin_distribution table + detects DRY_RUN mode from ecosystem config."}
{"d":"2026-05-14","t":"FEAT","m":"MCP Server: 2 new tools — find_equivalences (search 63k+ verified cross-brand mappings with confidence filter, returns FX alternatives + competitor matches formatted for LLM) + get_price_history (392k+ obs, daily series, per-vendor min/max/avg, cheapest source identification). Total: 21 MCP tools."}
{"d":"2026-05-14","t":"FIX","m":"Blog from URL: SPA-aware content extraction. fetchUrlContent() now extracts OG/meta tags (og:title, og:description, name=description, og:site_name) as fallback for JavaScript SPAs. Returns spaDetected=true when body text < 300 chars. from-url endpoint skips gatherBlogData() product injection when SPA detected prevents fo-blog model from defaulting to optical networking domain on non-networking URLs. additionalContext now includes explicit SPA warning + meta content. generated_by in pipeline UPDATE uses active model name (no more hardcoded 'fo-blog-engine-v7'). Dashboard shows SPA warning toast + spa_detected field in response."}
{"d":"2026-05-14","t":"FEAT","m":"Blog Engine: URL Blog feature. POST /api/blog/from-url fetches any URL server-side (20s timeout, redirect-follow), strips scripts/nav/footer/SVG, extracts readable text (~5000 chars) + page title, passes as structured additional_context to the 16-step FO blog pipeline. Dashboard: new '🔗 Blog aus URL generieren' panel with URL input (Enter key supported), Blog-Typ selector, loading state, and char count confirmation. Same pollBlogLlm() polling reused for step progress."}
{"d":"2026-05-14","t":"UI","m":"Switch modal Flexoptix section: (1) Speed formatting fixed 1600.00G 1.6T, 400G clean integer (fmtSpeed() helper, 1000 Gbps T). (2) Lagerbestand badges added per transceiver row: DE-Lager (green), Global-Lager (blue), Zulauf with ETA date (yellow). Data sourced from stock_observations via LEFT JOIN LATERAL in getFlexoptixSuggestions(). Badges hidden when quantities are null/0 (scraper not yet populating Flexoptix warehouse columns shows automatically once scraper is extended)."}
{"d":"2026-05-14","t":"FEAT","m":"Stock velocity API: GET /api/stock/velocity (paginated, filterable by vendor_id/confidence/stockout_days/min_sell_rate/part_number) + GET /api/stock/velocity/:id (per-product velocity summary + sell/zulauf event history). Both routes live in packages/api/src/routes/stock.ts, compiled + deployed to tip-api PM2 id 24, port 3201."}
{"d":"2026-05-14","t":"DATA","m":"Demo data cleanup: deleted 2133 demo rows from reorder_signals (is_demo_data=true). Stock observation coverage expanded: atgbics.ts + optcore.ts now call upsertStockObservation after each price observation (binary in/out stock, confidence=1). FS.com scraper already runs 3x daily from Mac (02:00/10:00/18:00) with full DE-Lager/Global-Lager/Nachlieferung breakdown. Competitor stock audit: QSFPTEK (confidence=2, real quantities), FS.COM (confidence=3, per-warehouse breakdown) are highest fidelity; ATGBICS/Optcore added at confidence=1 (binary); sfpcables/prolabs/wiitek hardcode or lack stock not added."}
{"d":"2026-05-13","t":"FIX","m":"BlogLLM model version sync: dashboard FO_BlogLLM card now dynamically reflects the active Ollama model via /api/blog/llm/status (was hardcoded to fo-blog-v7). TIP ecosystem.config.js OLLAMA_LLM_MODEL + BLOG_LLM_MODEL bumped fo-blog-v7 fo-blog-v10 (Mac Studio Magatama training adopted 2026-05-13 00:33 UTC). Persisted /opt/tip/blog-llm-settings.json overrode env also updated. tip-api restarted, PM2 state saved."}
{"d":"2026-05-13","t":"FEAT","m":"BlogLLM auto-discovery: client.ts now probes Ollama at startup + every 10 min, reconciles configured fo-blog-vN against actual available tags, auto-falls to highest available version when configured model no longer exists. Magatama-aware sort: base 'fo-blog-vN' tag wins over '-rM' revisions within same N (matches Magatama adoption convention where -rM is intermediate adapter save, base is production alias). New POST /api/blog/llm/refresh-discovery endpoint for manual trigger. Eliminates 3-step manual sync after every Magatama training."}
{"d":"2026-05-13","t":"FIX","m":"Ollama Modelfile bug for fo-blog-v10: Mac Studio adoption registered model with template '{{.Prompt}}' instead of Qwen2.5 chat template model returned empty responses to /api/chat. Recreated fo-blog-v10 via Ollama /api/create with correct ChatML template ({{- if .System}}<|im_start|>system ... <|im_end|>...), num_ctx=8192, stop=<|im_end|>, temperature=0.3. Smoke test: 45 tokens generated cleanly. Magatama-side adoption logic should be patched to emit correct template by default."}
{"d":"2026-05-13","t":"DATA","m":"Competitive naming sanitization + Anti-Naming-Policy training: (1) Sanitization sweep across all 244 JSONL training files: 97 Fs.com/FiberStore replacements with neutral 'unnamed third-party MSA-compatible vendor' across 15 active files (fo_blogllm, tip_llm pools + RunPod exports + historical RunPod pod-runs). All affected files backed up to .bak-fs-final/.bak-YYYYMMDD-HHMMSS. Post-sanitization verification: 0 assistant-content mentions of competitor brands across all 5 lanes (fo_blogllm, pulso_llm, tip_llm, magatamallm, contact_llm). Remaining FS mentions live only in system-prompt prohibition lists (anti-naming policy) and one magatamallm user-message context for legitimate internal SKU-matching research. (2) Anti-Naming-Policy training pairs added: 4 deep pairs for fo_blogllm (third-party market analysis, procurement strategy, coherent component stack), 3 pairs for pulso_llm (competitor-inquiry deflection, price-compare without naming, internal sales guidance), 1 pair for tip_llm (public research blog output with neutral language). All new system prompts contain explicit COMPETITIVE NAMING POLICY clause forbidding named mentions of Fs.com/FiberStore/Approved Networks/Cablexa/ProLabs/FluxLight + component suppliers Accelink/InnoLight/Lumentum/Coherent/II-VI/Eoptolink/Source Photonics. Switch and router OEMs (Cisco/Arista/Juniper/Nokia/Ciena/HPE/Dell/Mellanox/Extreme/Huawei) explicitly permitted as integration partners. Post-rebuild manifests: fo_blogllm 18757 effective, pulso_llm 3242 effective, tip_llm 2181 effective."}
{"d":"2026-05-13","t":"DATA","m":"FO_BlogLLM training corpus deep-quality expansion: 8 new training files in pulso_llm pool with 22 long-form (700-1000 word) blog pairs targeting fo-blog-v10 failure modes. Categories: (1) Connector Authority — MPO Type A/B/C polarity, IEC 61300-3-35 endface inspection, MPO-12 vs MPO-16, LC vs MPO architecture mapping; (2) Transceiver Taxonomy — full 100G/400G/800G variant matrix with reach, connector, lane structure, IEEE clauses; (3) Coherent Depth — coherent vs direct-detect crossover, OSNR engineering for ZR+, FEC types (cFEC/oFEC) and pre-FEC BER reality; (4) Power & Reach Ground Truth — accurate per-module power numbers 2026, OTDR commissioning workflow; (5) Operations Troubleshooting — pre-FEC BER climbs diagnostic walkthrough, module detection / coding mismatch fixes; (6) Topic Adherence — exact MPO Connector Survival Guide blog (the test prompt that failed in v10), Fiber Inspection Probes, Cable Routing for spine-leaf; (7) Standards Map — IEEE 802.3ba/cd/cu/df clause map, CMIS register layout; (8) Myth Corrections — DR ≠ Long Reach, LR vs ER vs ZR taxonomy, MPO-parallel vs LC-WDM architecture. All pairs include IEEE/OIF/MSA citations, real datasheet-equivalent numbers (TX/RX power, sensitivity, power consumption per module class). Pool now: 17936 train + 2018 eval = 19954 total after dedupe (123 duplicates removed). Next fo_blogllm training run picks up automatically."}
{"d":"2026-05-13","t":"FIX","m":"Magatama Mac Studio adoption template root cause patched: /opt/magatama/packages/fine-tuner/train.py register_ollama() built Modelfiles without TEMPLATE directive (only FROM/SYSTEM/PARAMETER) — Ollama defaulted to '{{.Prompt}}' which silently breaks /api/chat. Both modelfile_lines blocks (GGUF and fallback) now include the Qwen2.5 ChatML TEMPLATE plus full PARAMETER set (temperature 0.3 (was 0.1), top_p 0.9, num_ctx 8192, stop <|im_end|>). End-to-end test against Ollama API confirmed: model registers + /api/chat returns expected tokens. Future fo-blog-vN trainings (and any Magatama lane via Mac Studio path) will no longer produce silent-failure models. Backup at /opt/magatama/packages/fine-tuner/train.py.bak-20260513-153306. Local checkout synced. The other adoption path (/opt/llm-gateway/.../converter.py used by RunPod artifact import) already had TEMPLATE correct — no change there."}
{"d":"2026-04-26","t":"DATA","m":"Juniper OEM transceiver seed: 59 PIDs inserted (SFP-1GE/SFPP-10G/SFP-25G/QSFPP-40G/JNP-QSFP-100G/JNP-QSFP56-200G/JNP-QSFPDD-400G/JNP-OSFP-400G+800G + DAC/AOC). Scheduler: daily 04:15."}
{"d":"2026-04-26","t":"FIX","m":"BlueOptics scraper: force HTTP/1.1 via Node.js https.get() to bypass empty-body HTTP/2 server bug; updated catalog path to /Transceivers_1 (changed 2026)."}
{"d":"2026-04-26","t":"DATA","m":"Cisco TMG scraper: upsert logic fixed (market_status EOL + temp_range IND normalization). Full run in progress: 300+ switches, 15000+ compat matches written to switch_transceiver_compat."}
{"d":"2026-04-28","t":"INFRA","m":"Gitea repo tip-training-data created (https://gitea.context-x.org/rene/tip-training-data). Generated full-scope token via gitea admin CLI on 192.168.178.196."}
{"d":"2026-04-28","t":"AI","m":"crawler-llm/spec-validator.ts: transceiver physical plausibility validator — form factor↔speed matrix, wavelength↔fiber consistency, reach limits, IEEE standard cross-check, DAC/AOC rules. Outputs SpecValidationResult with tier (high/medium/low/rejected) + confidence_delta."}
{"d":"2026-04-28","t":"AI","m":"crawler-llm/training-data-writer.ts: TIPLLM SFT training data writer — generates spec_qa/crawl_reasoning/validation/discovery JSONL pairs from crawler extractions, git-commits and pushes to Gitea tip-training-data repo in batches of 50."}
{"d":"2026-04-28","t":"AI","m":"crawler-llm/vendor-discovery-crawler.ts: intelligent PlaywrightCrawler — vendor catalog URL → LLM extraction (core.ts) → spec validation → DB persist (findOrCreateScrapedTransceiver) + Gitea SFT training pairs. 8 vendor configs: Cisco/Juniper/Arista/FS.com/Flexoptix/Nokia/Huawei/II-VI."}
{"d":"2026-04-28","t":"INFRA","m":"scheduler.ts: 8 weekly vendor discovery jobs registered (discover:vendor:*), staggered Sun 20:00 Mon 10:00 UTC. Total workers: 102."}
Types: FEAT · FIX · UI · DATA · AI · INFRA
{"d":"2026-04-25","t":"FEAT","m":"Standards Audit + Form Factors Reference: expanded standards from 40 to 63 (+23 new: full 200G tier SR4/DR4/FR4/LR4/ER4/CR4, PON family GPON/XG-PON1/NG-PON2/25G-PON, copper DAC variants CR4 for 25G/40G/100G/400G, 800G emerging FR4/LR8/CR8, 1.6TBASE-DR16 emerging). All 63 standards have bilingual plain-language descriptions (DE+EN, for non-technical colleagues). New form_factors table (migration 101) with 20 entries: SFP family SFP→SFP112, QSFP family QSFP+→QSFP-DD800, OSFP family OSFP→OSFP224, CFP family, legacy XFP/CXP — with full names, channel count, max speed, hot-swap flag, supersedes chain, status, and bilingual descriptions. New GET /api/form-factors endpoint. Dashboard Standards tab: descriptions shown as table row subtitles, Form Factors grid section with family color coding, speed/channel info, openFormFactorDetail panel."}
{"d":"2026-04-25","t":"FEAT","m":"Flexoptix Internal Demand Intelligence: imported real sales velocity (8.585 SKUs, 1.288 with demand>0) from AES-256-CBC encrypted XLSX export into flexoptix_internal_demand table (PostgreSQL RLS enabled, is_internal guard). 279 SKUs cross-referenced with transceiver catalog. New /api/internal/demand/* endpoints (by-speed, velocity, hype-weights, forecast-input) — localhost/LAN only + JWT auth. Forecast engine now calibrated with real Flexoptix run-rates (demand_calibrated:true). Dashboard Warehouse tab updated: real Flexoptix Sales Velocity panel with momentum indicators replaces DEMO DATA. Fast movers: 70 SKUs ≥100/mo (SFP 1G + SFP+ 10G dominate). Total throughput: 63.328 units/month (12m basis). Data never leaves private infrastructure."}
{"d":"2026-04-25","t":"DATA","m":"Migration 099: flexoptix_internal_demand schema — table + RLS policies + indexes + v_demand_by_speed aggregated view. Security: raw SKU rows never exposed publicly; RLS enforces is_internal=TRUE; IP restriction middleware on all internal API routes."}
{"d":"2026-04-25","t":"DATA","m":"Migration 098: +5 Cisco ASR 9903/9900 line card images (A9903-8HG-PEC, A9903-8HG-PEC-FC, A9903-20HG-PEC-FC, A99-12X100GE-FC, A99-32HG-FC) via eBay CDN (i.ebayimg.com, 171302KB JPEGs). Coverage 663 → 668 (98.7%). Remaining 9 models confirmed no publicly accessible images: RA-B6920-4S (Ragile website unreachable), 8K-MPA-18Z1D (too new), Inventec D7332/D7264Q28B/D7054Q28B (Taiwan-hosted CDN), Datacom DM4610-48T6X, FiberHome CiTRANS 680, NEC PF5248, DZS OLT 9100."}
{"d":"2026-04-25","t":"DATA","m":"Migration 097: +2 whitebox switch images (Ragile RA-B6510-48V8C via unixsurplus.com BigCommerce CDN OEM-equiv hardware, Edgecore AS7946-74XKDB via eBay CDN). Remaining 7 non-Cisco models (Inventec D7332/D7264Q28B/D7054Q28B, Datacom DM4610-48T6X, FiberHome CiTRANS 680, NEC PF5248, DZS OLT 9100) have no publicly accessible product images."}
{"d":"2026-04-25","t":"DATA","m":"Migration 094 (fixed): +12 Cisco models (8K-MPA-4D/16H/16Z2D, A9K-8HG-FLEX-FC/SE/TR, A9K-400G-DWDM-TR, N9348Y12C-SE1, NC55-36X100G-A-SE, ASR-9000V-24-A, ASR-9000V-DC-E, ASR-9922-RP-TR). Fixed 4 bad URLs: Cisco DAM 404, fabricated BigCommerce URL, and 2 unreachable Magento/it-market URLs replaced with eBay CDN and NetworkTigers Shopify CDN."}
{"d":"2026-04-25","t":"FIX","m":"Umami analytics unreachable — UMAMI_PASS in /opt/tip/ecosystem.config.js was AES-256-CBC encrypted but TIP API passed it as plaintext to Umami → 401. Fixed: reset Umami admin password in DB with bcrypt hash, updated ecosystem.config.js UMAMI_PASS to plaintext, restarted tip-api with --update-env. Both http://localhost:3150 and https://analytics.fichtmueller.org now authenticate successfully. Dashboard sync-umami button no longer shows Fehler toast."}
{"d":"2026-04-25","t":"DATA","m":"Migration 093: NCS 5500 main line card image backfill — 6 models: NC55-18H18F (it-market.com 7KB), NC55-24X100G-SE (networkgenetics.net BigCommerce 317KB PNG), NC55-32T16Q4H-A (hummingbirdnetworks.com BigCommerce 32KB), NC55-36X100G-S (dedicatednetworksinc.com WordPress 1.2MB PNG), NC55-MOD-A-S (stack-systems.com Magento 5.5KB), NC55-MOD-A-SE-S (core92.com Odoo 52KB). Coverage: 644 → 650 (95.1% → 96.0%)."}
{"d":"2026-04-25","t":"DATA","m":"Migration 092: Cisco remaining image backfill — 48 models: A99-* ASR9900 line cards (27 models via router-switch.com CDN + SQL subquery from A9K equivalents + NetworkOutlet/ZionNetworking/NetworkTigers CDN), C9600-LC-24C/40YL4CD/48S/48YL + C9600-SUP-1 + C9600X-LC-32CD/56YL4C + C9600X-SUP-2 (NetworkTigers + ITBargainCenter CDN), NC55-MPA-4H-S/12T-S/2TH-S/1TH2H-S/4H-HX-S/4H-HD-S/2TH-HX-S + NC55-OIP-02 (router-switch.com 157KB), NC55-24H12F-SE (networkgenetics.net BigCommerce), A900-IMA-8CS1Z/8Z/8Z-L (NetworkTigers + router-switch), A9903-20HG-PEC (TopParagonResource webp), ASR-9922-RP-SE (NetworkTigers v=1748329200), A9K-4HG-FLEX-X-FC/SE (subquery). Coverage: 597 → 644 (88.2% → 95.1%)."}
{"d":"2026-04-21","t":"DATA","m":"Migration 091: Arista + Juniper SONiC HCL models — 7 models: 7060CX-32S (networktigers.com DCS-7060CX-32S-F), 7050QX-32 (networktigers.com DCS-7050QX-32-F), 7050QX-32S (networktigers.com DCS-7050QX-32S-F), 7170-32CD (networktigers.com DCS-7170-32C-F-new), 7280CR3-32D4 (networktigers.com DCS-7280CR3K-32D4-F, CR3K same chassis), QFX5200-32C-S (networktigers.com QFX5200-32C-AFO), QFX5210-64C (networktigers.com QFX5210-64C-AFO). All from SONiC HCL device list. Coverage: 616 → 623 (estimated)."}
{"d":"2026-04-21","t":"DATA","m":"Migration 090: Edgecore AS-series SONiC switches — 7 models: AS7312-54X (stordis.com WebP, XS chassis successor), AS7312-54XS (stordis.com 64KB WebP), AS7326-56X (edge-core.com DCS203-F 83KB PNG), AS7716-32X (stordis.com 50KB WebP), AS7816-64X (edge-core.com DCS500-A 99KB PNG), AS9716-32D (edge-core.com DCS510-A 78KB PNG), AS7512-32X (epsglobal.com 26KB JPEG). All from SONiC HCL Accton/Edgecore vendor. Estimated coverage: 609 → 616 (speculative, pending DB query)."}
{"d":"2026-04-21","t":"DATA","m":"Migration 089: Arista/Cisco/Juniper batch — 8 models: 7800R4-36D2-LC (Arista, arista.com official LC image 15KB PNG), 8101-32FH (Cisco 8000, router-switch.com 57KB JPEG), 8111-32EH (Cisco 8000, stack-systems.com Magento CDN 9.6KB JPEG), C9300X-24Y (networktigers.com 64KB JPEG), C9500-48Y4C (networktigers.com 50KB JPEG), N9K-C93108TC-FX3P (networktigers.com full-res 78KB JPEG), PTX10001-36MR (juniper.net image library Azure CDN 112KB JPEG), PTX10004 (juniper.net image library lbox variant 138KB JPEG). Coverage: 601 → 609 (89.6% → 90.8%)."}
{"d":"2026-04-21","t":"DATA","m":"Migration 088: Ubiquiti/Phoenix Contact — 3 models: USW-Enterprise-48-PoE (cdn.ecomm.ui.com 331KB PNG), USW-Aggregation (cdn.ecomm.ui.com 285KB PNG), FL SWITCH 7528-2S (rspsupply.com distributor CDN 94KB JPEG, Phoenix Contact product ID 2891026). Coverage: 598 → 601 (89.1% → 89.6%)."}
{"d":"2026-04-21","t":"DATA","m":"Migration 087: Cisco ASR 9000 license-variant reuse — 3 models: A9K-4HG-FLEX-FC (FC license = same hardware as -TR), A9K-8X100G-LB-TR (TR license = same hardware as -SE), A9K-4X100GE base (pre-licensing-split catalog number = same hardware as -SE). All physically identical to covered siblings. Coverage: 595 → 598 (88.7% → 89.1%)."}
{"d":"2026-04-21","t":"DATA","m":"Migration 086: Mixed vendor batch — 8 models: CX732Q-N/CX564P-N (Asterfusion, asterfusion.com WP CDN, 267KB+768KB PNG), 7130-48LB (Arista, Alta Technologies reseller CDN, 70KB PNG), ICX 7850-48FS (Ruckus, networktigers.com, 55KB JPEG), E810-CQDA2 (Intel, esaitech.com Shopify CDN, 78KB JPEG), FSP 3000 CloudConnect (Adtran/ADVA, nwrusa.com Shopify CDN, 1.8MB JPEG), MediorNet MicroN UHD (Riedel, riedel.net fileadmin CDN, 279KB PNG), nGeniusONE InfiniStreamNG (Netscout, netscout.com Pantheon CDN, 85KB WebP). Coverage: 587 → 595 (87.5% → 88.7%)."}
{"d":"2026-04-21","t":"DATA","m":"Migration 085: Mixed straggler batch — 6 new models + 3 Celestica CDN upgrades. New: N540-24Q2C2DD-SYS (Cisco TD CDN 524146.jpg, 213KB), Apollo 9900 Series/Ribbon (ribboncommunications.com Drupal CDN, 207KB), Seastone2/Celestica (ServeTheHome DX010 review photo, 108KB), Midstone-200i/Celestica (DS3001 equivalent, celestica.com/uploadedImages), RA-B6510-48V8C/Ragile (Micas M2-W6510 ODM equivalent, BigCommerce CDN, 334KB), QuantaMesh T7064-IX1D/QCT (hyperscalers.com T7064-IX4 EOL family image). Upgrades: DS3000/DS4000/DS5000 foleon CDN → celestica.com/uploadedImages. Coverage: 581 → 587 (86.6% → 87.5%)."}
{"d":"2026-04-21","t":"DATA","m":"Migration 084: Cisco ASR 9000 bulk — 62 A9K-* models: 8T/4-B/E/L (slash-format), 16T/8-B, 1X/2X/8X/16X 100GE line cards, 8X100G-LB-SE, 20HG-FLEX-FC/SE/TR, 24X10GE-1G-FC/SE/TR, 24X10GE-SE/TR, 2T20GE-B/E/L, 36X10GE-SE/TR, 40GE-B/E/L/SE/TR, 48X10GE-1G-FC/SE/TR, RSP440-LT/SE/TR, RSP880-SE/TR, SIP-700, MPA-1X100GE/1X200GE/1X40GE/20X10GE/20X1GE/2X100GE/2X10GE/2X40GE/32X1GE/4X10GE/8X10GE + 6 FC-license MPA variants (same hardware). Sources: networktigers.com Shopify CDN + cdn.shopify.com (networktigers raw CDN) + router-switch.com Magento CDN + cloudappliances.co.uk (WebP 20HG-FLEX). Coverage: 519 → 581 (77.3% → 86.6%)."}
{"d":"2026-04-21","t":"DATA","m":"Migration 083: Cisco NCS 5700 line cards (NC57-18DD-SE/24DD/36H-SE/36H6D-S/48Q2D-S/48Q2D-SE-S/MOD-S/MOD-SE-S) + MPA modules (NC57-MPA-12L-S/1FH1D-S/2D4H-S) + NCS 1014 optical transport (NCS1K14-2.4T-K9/L-K9/X-K9/TXL-K9) — 15 models. Sources: cisco.com/c/dam TD CDN (numbered image IDs 520004523807) + Cisco datasheet-c78-742016 JCR renditions (embedded PNG from NCS 5700 product datasheet). Coverage: 504 → 519 (75.1% → 77.3%)."}
{"d":"2026-04-21","t":"DATA","m":"Migration 082: Cisco ASR 9000 line cards (A9K-4HG-FLEX-TR/SE, A9K-4T-B/E/L, A9K-4T16GE-SE/TR, A9K-4X100GE-FC/SE/TR, A9K-MOD400-SE/TR, A9K-MOD80-SE/TR) — 13 models (4 skipped: A9K-8T-B/E/L use slash-format names; fixed in 084). Sources: networktigers.com Shopify CDN + router-switch.com Magento CDN. Coverage: 491 → 504 (73.2% → 75.1%)."}
{"d":"2026-04-21","t":"DATA","m":"Migration 081: Cisco NCS 560 IMA modules (N560-IMA-1W/2C/2C-DD/8Q/4L), NCS 540 fixed (N540-24Q8L2DD/6Z14S/6Z18G-A/D/FH-AGG/FH-CSR), NCS 540X (N540X-4Z14G2Q/6Z18G/8Z16G/12Z16G/16Z8Q2C/ACC), ASR-9900-RP-SE/TR — 22 new + upgrade ASR-9902/9903 NCS1001/1002 to official Cisco CDN. Sources: cisco.com/c/dam TD CDN, manualslib.com, eBay CDN, signellent.com, brightstarsystems.com. Coverage: 469 → 491 (69.9% → 73.2%)."}
{"d":"2026-04-21","t":"DATA","m":"Migration 080: Avaya (ERS 4950GTS-PWR+), Advantech (EKI-7720G-4FI, EKI-9516G-4GMXP) — 3 images. Sources: planetrefurbished.com Shopify CDN + advdownload.advantech.com official product CDN. Coverage: 466 → 469 (69.4% → 69.9%)."}
{"d":"2026-04-21","t":"DATA","m":"Migration 079: WAGO (852-1505), WatchGuard (Firebox M5800), ADTRAN (NetVanta 1560-48P), Phoenix Contact (FL SWITCH 4808E-16FX-4GC) — 4 images. Sources: gilautomation.com Shopify CDN, watchguard.com help-center CDN (1MB PNG), portal.adtran.com ProductCatalog, rspsupply.com. Coverage: 462 → 466 (68.9% → 69.4%)."}
{"d":"2026-04-21","t":"DATA","m":"Migration 078: Cisco ASR-9001-S, ASR-9000V-AC/DC-A, A9KV-V2-DC-A/DC-E (specific images), NCS1001-K9, NCS1002-K9, NCS1K-EDFA, and 13 NCS1K4/NCS1004 chassis variants — 21 models. Sources: networktigers.com Shopify CDN + router-switch.com Magento CDN (145KB NCS1004 chassis). Coverage: 443 → 462 (66.0% → 68.9%)."}
{"d":"2026-04-21","t":"DATA","m":"Migration 077: Barracuda Networks (CloudGen Firewall F900), Peplink (SD Switch 24-Port), Westermo (Lynx 5612-F4G-T8G) — 3 images. Sources: cdn.blueally.com partner CDN + westermo.eworldme.com Shopify CDN. Coverage: 440 → 443 (65.6% → 66.0%)."}
{"d":"2026-04-21","t":"DATA","m":"Migration 076: QCT/QuantaMesh (T7032-IX1, T7064-IX4, T9032-IX9), QNAP (QSW-M5216-1T), Sophos (CS210-48FP) — 5 images. Sources: qct.io CDN, hyperscalers.com (T7064-IX4 EOL), cdn.blueally.com qnapworks, Sophos ContentStack CDN. Coverage: 435 → 440 (64.8% → 65.6%)."}
{"d":"2026-04-21","t":"DATA","m":"Migration 075: Cisco Nexus 9300 SE1 series (N9324C-SE1U, N9336C-SE1, N9348Y2C6D-SE1U, N9364E-SG2-O, N9364E-SG2-Q, N9396T12C-SE1, N9396Y12C-SE1) — 7 images. Sources: cisco.com/content/dam/cisco-cdc poster-image CDN + cisco.com/c/dam/assets support CDN. Coverage: 428 → 435 (63.8% → 64.8%)."}
{"d":"2026-04-21","t":"DATA","m":"Migration 074: Extreme Networks (SLX 9740-40C, X695-48Y-8C, 5520-48T), Ruijie (RG-S6920-4C, RG-S5760C-24SFP/8GT8XS-X), Ruckus (ICX 7150-48PF, ICX 7550-48ZP), ZTE (ZXR10 5960-56PM-H, ZXR10 9908), Edgecore (AS7712-32X) — 10 images. Coverage: 418 → 428 (62.3% → 63.8%)."}
{"d":"2026-04-21","t":"DATA","m":"Migration 073: Cisco ASR 9000 + NCS 540 series images — 18 standalone chassis entries (ASR-9001/9901/9902/9903 + A9KV-V2 variants + N540/N540X variants). Sources: networktigers.com Shopify CDN + tempestns.com WP CDN. Coverage: 400 → 418 (59.6% → 62.3%)."}
{"d":"2026-04-21","t":"INFRA","m":"12-hour DB backup to home server (Mac Studio): /opt/tip/backup-db.sh script + cron 0 0,12 * * * on Erik. First backup: 32MB gzipped pg_dump, rsync over WireGuard VPN, keeps last 10 remote + 5 local."}
{"d":"2026-04-21","t":"DATA","m":"Migrations 065-072 applied to production DB: Cisco (14 models), Juniper (10), Arista remaining (11), NVIDIA/Mellanox (5), Huawei/Nokia (7), Dell/Extreme (7), HPE Aruba/Ubiquiti/Supermicro (8), Celestica/Asterfusion/FS.com/Edgecore (10). Total: +73 switches with images on live DB."}
{"d":"2026-04-21","t":"FIX","m":"Volume data loss prevention: docker-compose.yml updated to use external: true volumes with explicit names (tip_tip_pgdata, tip_tip_qdrant) + restart: unless-stopped on postgres/qdrant. Prevents accidental volume recreation on compose up."}
{"d":"2026-04-21","t":"FIX","m":"Production DB restored from correct volume: tip_tip-pgdata (354MB, 8995 transceivers, 350 vendors, 97K price obs) rsync'd to tip_tip_pgdata (which was a fresh empty DB from wrong compose config). DB now has correct data. Standards (029-seed-standards.sql) applied: 40 rows."}
{"d":"2026-04-21","t":"INFRA","m":"GitHub push gates hardened: pre-push hook installed in transceiver-db repo (.git/hooks/pre-push) — triple security scan (secrets/private IPs/config values) runs before every push to GitHub public repo."}
{"d":"2026-04-18","t":"AI","m":"Blog LLM: claude-code provider implemented in packages/api/src/llm/client.ts — routes BLOG_LLM_PROVIDER=claude-code to claude-bridge (http://localhost:3250/api/generate) on Erik using Claude Code flat-rate subscription. No API billing. checkHealth() pings /health endpoint. Dashboard updated: added claude-code card (EMPFOHLEN, AKTIV), fo-blog-v3-qwen7b card replaced with fo-blog-v5, loadBlogLLMStatus() now handles claude-code provider with correct badge/border highlighting. ecosystem.config.js + .env updated: OLLAMA_LLM_MODEL=fo-blog-v5, BLOG_LLM_PROVIDER=claude-code confirmed active via pm2 env."}
{"d":"2026-04-18","t":"FIX","m":"Cloudflare Tunnel DNS mass-update: after deleting phantom eo-pulse tunnel and creating main-prod (90c22eb0), 31 context-x.org + 7 fichtmueller.org DNS records still pointed to the deleted 641c39a5 tunnel → 530 on all services. Bulk-patched via Cloudflare API: all records now point to main-prod. Created missing admin.magatama.fichtmueller.org CNAME. TIP cloudflared-tip.service restart policy changed to Restart=always (was on-failure, so clean exits caused permanent outage). peercortex.org remains 530 — DNS is in a separate inaccessible Cloudflare account (NS: fattouche/elisabeth.ns.cloudflare.com); needs manual login."}
{"d":"2026-04-18","t":"DATA","m":"Image backfill: GBICS og:image + QSFPTEK backfill scripts run on Erik — 226 new images added (671 → 897 total, 17.5% → 23.4% coverage). OSFP form factor: 0 → 68 images. QSFPTEK og:image URL bug fixed (double-hostname prefix stripped). OSFP-DR8-800G manually set to GBICS-compatible image (cdn11.bigcommerce.com DR8 product photo)."}
{"d":"2026-04-18","t":"FIX","m":"FS.com scraper: all 247 prices written as €79 (wrong) — root cause: 'Gratis Versand ab 79 € (ohne MwSt.)' free-shipping banner appears on every FS.com product page. PRICE_QUALIFIED bodyText regex matched this banner text before reaching the actual product price. Fix: (1) DOM-based price extraction added to page.evaluate — targets [class*='price-value']/[class*='product-price'] etc., skipping elements inside shipping/banner/footer parents; (2) bodyText qualified patterns now check 200-char context for versand/shipping/gratis keywords and skip matches that appear in shipping context; (3) waitForSelector for price elements added before evaluate; (4) deleted 247 invalid €79 observations from DB."}
{"d":"2026-04-18","t":"FIX","m":"has_image flag desync: 671 transceivers had image_url set but has_image=false. Fixed: (1) db.ts findOrCreateScrapedTransceiver now sets has_image=true, image_verified=true on both INSERT (ON CONFLICT DO UPDATE) and UPDATE path; (2) DB bulk UPDATE SET has_image=true WHERE image_url IS NOT NULL AND has_image=false (632 rows fixed)."}
{"d":"2026-04-18","t":"FIX","m":"Fiber type missing for 400G/800G parallel-optic modules (DR8/SR8/FR8 etc.): spec-updater parseSpecTable did not recognize standard abbreviations. Added DR/FR/LR/ER/ZR → SMF and SR → MMF patterns for both 'Fiber Type' field values and part-number-style keys. DB bulk UPDATE applied: 55 transceivers set to SMF, 20 to MMF."}
{"d":"2026-04-18","t":"FIX","m":"Dashboard blog generation: both generateBlog() and generateBlogManual() were calling POST /api/blog/generate without Authorization: Bearer header. requireAuth middleware correctly returned 401, shown as 'Unauthorized — please log in' toast. Fixed: read loadToken() before each fetch and include token in header. Also added r.status===401 guard to redirect to login page on token expiry."}
{"d":"2026-04-18","t":"FIX","m":"PM2 SKIP_FS_SCRAPER env not picked up by tip-scraper-daemon: pm2 restart --update-env did not apply new ecosystem.config.js vars because PM2 loaded from its saved dump. Fixed: pm2 delete + pm2 start ecosystem.config.js --only tip-scraper-daemon + pm2 save. Daemon restarted fresh (ID 83, 0 restarts) with SKIP_FS_SCRAPER=true now confirmed live. FS.com job now correctly skips on Erik instead of failing with ENOENT."}
{"d":"2026-04-18","t":"FIX","m":"FS.com Mac scraper: suppress Crawlee post-run ENOENT unhandledRejection — Crawlee's FileSystemStorage fires a final _isTaskReadyFunction call after run() resolves, reading a request .json that was already processed/cleaned-up. This ENOENT triggered process.exit(1) before Phase 2 completed, causing 7 days of missing FS.com price data. Fixed: targeted unhandledRejection handler in require.main block swallows ENOENT from request_queues paths while re-raising real errors."}
{"d":"2026-04-18","t":"FIX","m":"FS.com Mac scraper: PID lock (/tmp/tip-fs-scraper.lock) added to run-fs-scraper-mac.sh — prevents concurrent instances when launchd 2am fire overlaps with a still-running earlier run. Previous concurrent instances caused rmSync(storage-fs-phase1) race (one instance deletes the storage dir while another is using it), crashing Phase 2."}
{"d":"2026-04-18","t":"FIX","m":"Scraper health monitor: tiered alerts replacing false-positive 6h threshold. Old: fired every 3h for any vendor with 0 new prices (including stable prices). New: 🔴 CRITICAL (last price >7 days), 🟡 WARNING (last price 48h-7 days), ✅ STABLE (0 new prices but last price ≤48h — content hash dedup, scraper running OK). Shows pg-boss job state+time for faster root-cause."}
{"d":"2026-04-18","t":"FIX","m":"Daemon stability: global unhandledRejection handler in scheduler index.ts — Crawlee post-run lock-file ENOENT (request_queues path) was crashing the daemon process (process.exit(1)) which killed all active pg-boss jobs and triggered PM2 restart loops. Fix: swallow ENOENT from request_queues paths at the scheduler level; re-raise all other rejections. Also: FS.com scheduler worker now skips (SKIP_FS_SCRAPER=true env var) on Erik where Cloudflare WAF blocks datacenter IPs; Mac launchd handles FS.com scraping. Created missing Crawlee storage dirs: storage-fs-phase1, storage-fs-phase2, storage-ebay-transceivers, storage-fs. Health monitor pg-boss lookup extended from 12h → 26h; added completedMap; vendors with recent job completion + historical prices classified as STABLE (not CRITICAL) — eliminates ATGBICS/Fluxlight false-positive alerts."}
{"d":"2026-04-18","t":"FIX","m":"Playwright chromium_headless_shell-1217 installed on Erik (/opt/playwright-browsers/): ATGBICS and FS.com PlaywrightCrawler were throwing BrowserLaunchError on every run since Crawlee browser-pool requires chromium_headless_shell binary, not regular chromium. Fixed by: PLAYWRIGHT_BROWSERS_PATH=/opt/playwright-browsers npx playwright install chromium --with-deps on Erik."}
{"d":"2026-04-18","t":"FIX","m":"Crawlee withIsolatedStorage global env-var race condition eliminated: scheduler.ts removed all withIsolatedStorage() wrappers (were mutating process.env.CRAWLEE_STORAGE_DIR globally, causing concurrent scrapers to pick up wrong storage dirs). All Crawlee scrapers now use makeCrawleeConfig(name) instance-level Configuration. fs-com.ts migrated to fs-phase1/fs-phase2 storage names with rmSync cleanup before each phase. switch-assets-crawler.ts and switch-assets-playwright.ts now pass makeCrawleeConfig. Fixed: ATGBICS, community-issues, market-intel, FS.com."}
{"d":"2026-04-18","t":"FIX","m":"FS.com Mac launchd scraper (org.tip.fs-scraper): was failing with exit code 126 (Operation not permitted) because macOS TCC blocks launchd agents from accessing ~/Desktop/Claude Code/ path. Fixed: script moved to ~/.tip/run-fs-scraper-mac.sh, plist WorkingDirectory changed to ~/.tip. FS.com is now scraping from residential Mac IP again."}
{"d":"2026-04-18","t":"FIX","m":"NADDOD stockLevel 'unknown' -> 'on_request': invalid value for price_observations_stock_level_check constraint — was causing all NADDOD price insertions to fail."}
{"d":"2026-04-18","t":"FIX","m":"Crawlee makeCrawleeConfig: clear request_queues/default before each run — Crawlee FileSystemStorage marks URLs as HANDLED (state=4, orderNo=null) after processing. With purgeOnStart=false these entries persisted, so next crawler.run(startUrls) deduplicated all startUrls → requestsTotal=0 → immediate finish with 0 scraped pages. Fix: rmSync(request_queues/default) at start of makeCrawleeConfig(). Safe: session pool lives in key_value_stores/, not request_queues/. ATGBICS confirmed fixed: now scrapes 6 categories, 78 products, 33 unique with prices."}
{"d":"2026-04-18","t":"FIX","m":"Optcore scraper: add SKIP_OPTCORE_SCRAPER guard — optcore.net Cloudflare WAF blocks Erik IP (82.165.222.127). WP REST API returns 403/HTML block page, catch handler returns 0 URLs → 0 products every run. Set SKIP_OPTCORE_SCRAPER=true in ecosystem.config.js. Pattern mirrors SKIP_FS_SCRAPER. Residential IP (Mac launchd) required for Optcore."}
{"d":"2026-04-18","t":"FIX","m":"10Gtek scraper: was finding 152 products but 0 prices — 10gtek.com main site only shows technical spec tables (no prices). Rewrote scraper to target sfpcables.com (10Gtek's own retail store, same company) which exposes Magento product listings with Model: <part> + US$X.XX prices. Added Magento loop-detection via seen-part dedup (stops pagination when all products on a page were already seen). XFP title-after-pipe fallback for part number extraction. Removed QSFP-DD (not on sfpcables.com). Result: 50 products, 49 prices on first live run. Health monitor CRITICAL alert resolved."}
{"d":"2026-04-18","t":"FEAT","m":"Price Comparison Dashboard: public /api/price-comparison (summary, list top-50 SKUs by vendor coverage, per-SKU detail). Express Router, no auth required. New '💲 Price Comparison' dashboard tab with stat cards, form-factor breakdown table, top-50 SKU table (clickable rows), and SKU detail lookup with per-vendor prices + stock + spread %."}
{"d":"2026-04-18","t":"DATA","m":"Eoptolink OEM catalog scraper: harvests 93 product-solution pages from eoptolink.com, extracts part numbers (EOLO-*/EOLQ-* format), seeds transceivers table as manufacturer=Eoptolink entries with form_factor/speed/fiber/category. No prices (B2B OEM). Scheduled every 4h (40 */4 * * *)."}
{"d":"2026-04-18","t":"FIX","m":"stock_observations repopulated after TRUNCATE: storage-fs/request_queues/default/ directory re-created on Erik; NADDOD scraper manual-triggered; 4+ prices confirmed written within 20s."}
{"d":"2026-04-17","t":"FEAT","m":"MCP Server v0.2.0: wired finder.ts (find_flexoptix_for_switch, get_competitor_alerts), switch-docs (get_switch_docs, get_switch_image), analyze_market_with_llm (qwen2.5:14b via Ollama, enriched with live hype cycle + pricing + news), generate_blog_post (fo-blog-v5 fine-tuned model with qwen2.5:14b fallback + live pricing enrichment). OLLAMA_BASE_URL env var for Ollama endpoint."}
{"d":"2026-04-17","t":"UI","m":"Stock dashboard: 6th stat card (Multi-Vendor SKUs), confidence quality badge column in vendor breakdown (🟢 L3 per-warehouse / 🟡 L2 aggregated / ⚪ L1 boolean), new Multi-Vendor Price Comparison table with min/max/avg per SKU. Subtitle updated to mention QSFPTEK + NADDOD."}
{"d":"2026-04-17","t":"FEAT","m":"/api/stock/summary enhanced: vendor_breakdown adds avg_confidence + currencies + confidence breakdown (conf_per_warehouse/aggregated/boolean); new price_comparison endpoint (top 50 SKUs tracked by 2+ vendors with price spread); totals adds multi_vendor_skus count."}
{"d":"2026-04-17","t":"DATA","m":"Cisco TMG expanded to 17 platform families (+5 new: 8000 Series, NCS5500, NCS540, NCS560, NCS1000). Per-device query strategy replaces family-level search: iterates all switch IDs from filter → 58 switches per N9300 vs 1 before. 856 compat entries / 174 switches after re-run."}
{"d":"2026-04-17","t":"DATA","m":"Juniper HCT scraper run: 475 Juniper-brand transceivers seeded into transceivers table (form factor, speed, reach, fiber type from apps.juniper.net/hct). No prices (OEM). Scheduled to run at 6:15 + 18:15 daily."}
{"d":"2026-04-17","t":"DATA","m":"Competitor research: QSFPTEK shows real-time aggregated stock count (e.g. '5507 in real-time stock, 17 Apr 2026') + USD prices; NADDOD shows exact per-product counts ('In Stock: 543') via Astro SSR. Both scraped publicly, no login required. Flexoptix confirmed exact Lagerbestand + EUR prices. FS.com: EUR prices yes, exact counts no."}
{"d":"2026-04-17","t":"DATA","m":"stock_observations selective cleanup + schema upgrade: TRUNCATE stock_observations (186 FS.com test-run rows cleared, will repopulate on next launchd run). Added 4 new quality columns via migration 038: stock_confidence (1=boolean/2=aggregated/3=per-warehouse), price_currency CHAR(3), price_includes_tax BOOLEAN, stock_vendor_ts TIMESTAMPTZ."}
{"d":"2026-04-17","t":"FEAT","m":"Migration 028 retroactively committed to repo (028-stock-observations-warehouse-columns.sql) — documents the 10 warehouse columns applied directly to Erik DB. Guards with IF NOT EXISTS for safe re-application."}
{"d":"2026-04-17","t":"FEAT","m":"upsertStockObservation upgraded: new optional params stockConfidence (1|2|3), priceCurrency (ISO 4217), priceIncludesTax (boolean), stockVendorTs (timestamptz). FS.com now writes stockConfidence=3+priceCurrency=EUR+priceIncludesTax=false. Delta detection now also checks quantity_available changes."}
{"d":"2026-04-17","t":"FEAT","m":"QSFPTEK scraper v2: Phase 1 uses existing /mall/commodity/list API for product catalog (880+ products from sitemap). Phase 2 fetches /en/product/XXXXX.html detail pages to extract 'X in real-time stock, DATE' — writes stock_observations with stockConfidence=2 + stockVendorTs. Up to 500 detail pages per run at 2s rate limit."}
{"d":"2026-04-17","t":"FEAT","m":"NADDOD scraper v2: complete rewrite — migrated from WooCommerce category scraping to Astro sitemap-based discovery (/sitemaps/products.xml, /products/XXXXX.html). Extracts 'In Stock: X' exact counts from server-rendered HTML. Writes both price_observations (USD) and stock_observations (stockConfidence=1 or 2 depending on data visibility)."}
{"d":"2026-04-17","t":"DATA","m":"FS.com first warehouse data load: 268 products scraped, 186 stock_observations written — DE-Lager 128,428 units, Global-Lager 156,052 units, Backorder 37,495, 53.4M units sold total. Top seller: SFP-10GSR-85 with 14M units sold."}
{"d":"2026-04-17","t":"FIX","m":"upsertStockObservation: skip condition now includes backorder_qty — backorder-only products (DE=0 GL=0 BO>0) like coherent ZR/ZRH were silently dropped instead of being recorded"}
{"d":"2026-04-17","t":"FIX","m":"FS.com price extraction: broad fallback regex now only accepts prices >€100 to reject FS.com's €79 'Preis auf Anfrage' placeholder — prevents fake price observations on 1G/10G/25G/40G/100G transceivers"}
{"d":"2026-04-17","t":"UI","m":"Dashboard: stock observations count in header stats bar + warehouse stock summary card in Overview tab (hidden until stock_observations populated); both driven by /api/health stock block"}
{"d":"2026-04-17","t":"FEAT","m":"Health API: /api/health now includes stock block — total_observations, transceivers_with_stock, vendors_with_stock, total_de_qty, total_global_qty, last_observation_at from stock_observations"}
{"d":"2026-04-17","t":"INFRA","m":"FS.com Mac-side runner: launchd plist at 02:00/10:00/18:00 + run-fs-scraper-mac.sh via SSH tunnel to Erik DB port 5433 — residential IP required, datacenter IP blocked by FS.com Cloudflare WAF"}
{"d":"2026-04-17","t":"FEAT","m":"Stock API: GET /api/stock, /api/stock/summary, /api/stock/:id — warehouse breakdowns (DE-Lager, Global-Lager, Nachlieferung, units_sold) per transceiver/vendor"}
{"d":"2026-04-17","t":"DATA","m":"upsertStockObservation() in db.ts — writes 10 new stock_observations columns (warehouse_de_qty, warehouse_global_qty, backorder_qty, units_sold, compatible_brands, price_net, product_url, delivery dates)"}
{"d":"2026-04-17","t":"DATA","m":"FS.com scraper v2: Playwright-based, extracts DE-Lager + Global-Lager + Nachlieferung + Verkauft counts, German number/date parsing, 120-URL pre-queue, 12-category crawl, 12h dedup window"}
{"d":"2026-04-17","t":"FIX","m":"SmartOptics scraper v2: WooCommerce REST API fallback + 8 catalog categories + relative URL regex fix — was finding only 8 products, now discovers full catalog"}
---
{"d":"2026-04-12","t":"FIX","m":"DB functions compute_transceiver_verification() + compute_transceiver_verification(uuid): both now require competitor_verified as 4th criterion for fully_verified — was silently ignoring competitor check and granting ★ 100% badge based on only 3 criteria"}
{"d":"2026-04-12","t":"FEAT","m":"Scheduler: maintenance:reconcile-verification nightly job (01:00 UTC via pg-boss) — auto-resets competitor_verified=false where no non-Flexoptix price_observation in last 30 days, then recomputes fully_verified — eliminates recurring false ★ 100% badges without manual SQL intervention"}
{"d":"2026-04-12","t":"DATA","m":"Data quality: 608 transceivers had competitor_verified=true with NO actual non-Flexoptix price in last 30 days — all reset to false + fully_verified=false. ★ 100% badge now only shows when genuinely earned. Triggered by user catching false badges on 1.6T OSFP products."}
{"d":"2026-04-12","t":"FIX","m":"ATGBICS + FS.COM scrapers: PlaywrightCrawler useSessionPool=false added — eliminates SDK_SESSION_POOL_STATE.json crash on every run; withIsolatedStorage now pre-seeds empty session state file as belt-and-suspenders"}
{"d":"2026-04-12","t":"FIX","m":"Skylane scraper: pagination now breaks on zero NEW unique product URLs (was looping all 10 pages because Algolia returns same content regardless of ?page=N)"}
{"d":"2026-04-12","t":"FIX","m":"AscentOptics scraper fully rewritten: uses /product-list?is_render=1&category_id=CID JSON API (was hitting 404 on old /catalog/ URLs); hardcoded category IDs for 14 transceiver form factors; no prices (OEM Get Quote model)"}
{"d":"2026-04-12","t":"UI","m":"Dashboard transceiver table: VERIFIED column now shows all 4 individual criteria per row (✓/— P=Price, I=Image, D=Details, C=Competitor) in green/red — ★ 100% badge only when all 4 met; uses competitor_verified DB column"}
{"d":"2026-04-12","t":"FIX","m":"Data quality: 59 anomalous price observations deleted (FS.COM accessories EUR 1-18 misidentified as OSFP/QSFP-DD/QSFP28; ATGBICS QSFP-DD sub-$60) — 49 transceivers competitor_verified degraded to false, 1 fully_verified badge removed"}
{"d":"2026-04-12","t":"FIX","m":"upsertPriceObservation: hard floor $1.50 USD added before form-factor bounds check — catches accessories/cables misidentified as transceivers when form_factor defaults to SFP with loose [2,3000] bounds"}
{"d":"2026-04-12","t":"FIX","m":"GBICS scraper: attribute order changed on site — regex updated from aria-label→href→data-event-type to dual-pass href+aria-label (both orders), data-event-type no longer required; prices now correctly extracted"}
{"d":"2026-04-12","t":"FIX","m":"Scheduler: 11 missing boss.work() handlers added for lightweight scrapers (fluxlight, gbics, optcore, champion-one, sfpcables, blueoptics, fiber24, tscom, skylane, ascentoptics, gaotek) — jobs were queued by cron but never consumed; scrapers stale 24-48h"}
{"d":"2026-04-12","t":"FIX","m":"withIsolatedStorage: removed rmSync cleanup of Crawlee storage dir — dir deletion caused SDK_SESSION_POOL_STATE.json not found crash on every Playwright scraper restart (ATGBICS/FS.COM failed every 2h cycle)"}
{"d":"2026-04-12","t":"FEAT","m":"Scheduler: monitor:scraper-health job added (every 3h via pg-boss) — checks price_observations per vendor in last 6h, logs SCRAPER HEALTH ALERT to pm2 stderr for any vendor with 0 new prices"}
{"d":"2026-04-12","t":"FIX","m":"Health check vendor names corrected: SFPCables→SFPcables, Fiber24→ShopFiber24, T&S Com→T&S Communication to match actual vendor table values"}
{"d":"2026-04-12","t":"FIX","m":"FiberMall scraper: URL schema corrected — wrong /c/1g-sfp-transceiver/ paths (HTTP 404) replaced with actual /store-XXXXX-name.htm category URLs discovered via homepage navigation scrape"}
{"d":"2026-04-12","t":"FIX","m":"FiberMall parser: product card split on new_proList_mainListLi (Vue.js SSR), price extracted from <span class=currency_price data-price=X.XX> — fixed false-match on data-price=0.00 from SKU variant items that appears before real price in each card"}
{"d":"2026-04-12","t":"FIX","m":"FiberMall: also scrapes SKU brand variants from .sku_item divs within each product group (Cisco/Arista/Juniper compatible versions listed per product)"}
{"d":"2026-04-12","t":"FIX","m":"Flexoptix price parsing: EUR text regex /([\d.]+)\s*EUR/ matched only digits before thousand separator (2,921.60 EUR → 2 EUR) — fixed to /([\d,]+\.?\d*)\s*EUR/ with comma strip; affects all Flexoptix prices >999 EUR"}
{"d":"2026-04-12","t":"FIX","m":"Flexoptix catalog: O.138HG2.C.05 (1.6T OSFP224 2x DR4) price corrected 3009.60→2921.60 EUR (stale since 2026-04-09, Flexoptix.net shows FLEXBOX price 2921.60 via data-price-amount attribute)"}
{"d":"2026-04-12","t":"FEAT","m":"Flexoptix catalog: 4 new search queries added — OSFP224 1.6T, OSFP224, 1.6T DR4, 1.6T transceiver — covers new 1.6T form factor previously missing entirely from catalog scraper"}
{"d":"2026-04-12","t":"FIX","m":"Schema: competitor_verified + competitor_verified_at columns added to transceivers table (ALTER TABLE) — were referenced in db.ts upsertPriceObservation but not in schema, causing price writes to fail silently for all competitor vendors (FiberMall, QSFPTEK etc.)"}
{"d":"2026-04-11","t":"FEAT","m":"Scraper coverage expansion: 3 new scrapers added — FiberMall (fibermall.com, USD), Vcelink (vcelink.com, USD, Shopify), OpticsBay (opticsbay.com, USD, WooCommerce) — all wired into scheduler and Pi fleet"}
{"d":"2026-04-11","t":"FIX","m":"QSFPTEK scraper fully rewritten: site migrated from OpenCart to custom Java/Spring+Vue — old /c/*.html paths 404, now uses /mall/commodity/list API with attribute-based data rate filtering; 8 attribute IDs for 1G/10G/25G/40G/100G/200G/400G/800G"}
{"d":"2026-04-11","t":"INFRA","m":"Scheduler: 61 workers total, 53 cron schedules — FiberMall/Vcelink/OpticsBay added at :03, :07, :57 past even hours"}
{"d":"2026-04-09","t":"FEAT","m":"Price anomaly detection: PRICE_BOUNDS per form-factor in db.ts upsertPriceObservation — prices outside [min,max] USD range silently rejected to prevent garbage data (e.g. SFP+ [4, 5000], OSFP224 [200, 60000])"}
{"d":"2026-04-09","t":"UI","m":"Dashboard: LLM panel redesigned for light theme readability; LLM model selector added to Blog Engine tab"}
{"d":"2026-04-09","t":"INFRA","m":"Pi Starlink proxy-agent: scraper routes selected lightweight scrapers exclusively to Pi worker fleet via SOCKS5 — no Playwright traffic on Pi nodes"}
{"d":"2026-04-09","t":"DATA","m":"800G standards deep enrichment: migration 033 — IEEE 802.3df, OIF 800G IA, 800G MSA, OSFP MSA, QSFP-DD800 MSA with links, status, timeline"}
{"d":"2026-04-09","t":"FEAT","m":"Linecard system support: switches can have linecard slots; Cisco 8000 accuracy migration (031) with correct port count and linecard data"}
{"d":"2026-04-09","t":"FIX","m":"Qdrant init, switch column verification, crawler live status, demo data badges — stability audit fixes"}
{"d":"2026-04-08","t":"FEAT","m":"Scraper: SOCKS5 proxy rotation for FS.com, ATGBICS, GBICS via Pi fleet nodes — residential IPs for CloudFront WAF bypass"}
{"d":"2026-04-07","t":"AI","m":"Blog fine-tuning: 100 gold-standard training articles added (blog-001 to blog-100) for fo-blog-v2/v3 fine-tuning dataset"}
{"d":"2026-04-06","t":"FIX","m":"Scraper: FS.com switched to de.fs.com for EUR prices as primary source; parsePrice hardened (requires currency symbol, uses largest number)"}
{"d":"2026-04-06","t":"FIX","m":"Scraper: bot User-Agents replaced with Chrome UA; dead domain scrapers disabled"}
{"d":"2026-04-06","t":"FIX","m":"Blog: Claude API calls serialized via queue to prevent 429 rate-limit spam; claudeQueue deadlock from recursive 429 retry fixed"}
{"d":"2026-04-06","t":"FEAT","m":"Blog: Anthropic Claude provider added to LLM client — claude-bridge on Erik used as flat-rate backend"}
{"d":"2026-04-06","t":"DATA","m":"Migrations 026+027: price observation cleanup and FS.com EUR currency fix"}
{"d":"2026-04-06","t":"FIX","m":"Dashboard: verified badge logic corrected; comparable pricing shown properly; product images clickable"}
{"d":"2026-04-06","t":"AI","m":"Blog training: 13 gold-standard articles added to BlogLLM training set"}
{"d":"2026-04-05","t":"FEAT","m":"Blog Engine: AEM/APM pipeline steps + SLL context builder + LinkedIn v2 prompts; blog routes mounted (blogSllRouter + scraperRouter)"}
{"d":"2026-04-05","t":"FEAT","m":"Blog: Title Contract + Technical Sanity Check + Self-Heal + angle-aware LinkedIn generator; anti-repetition engine with 6 angle types and forbidden structures"}
{"d":"2026-04-05","t":"FEAT","m":"Blog: Post to Ghost + Post to LinkedIn buttons in dashboard"}
{"d":"2026-04-05","t":"FIX","m":"Blog: hard story blacklist in STEP4 + LinkedIn (2AM/dirty connector/lab-vs-prod stories banned); word target 12001600; power-budget false positive fix"}
{"d":"2026-04-05","t":"FEAT","m":"Dashboard: data verification status section added to Overview tab"}
{"d":"2026-04-05","t":"FEAT","m":"Scraper: all pricing scrapers unified to 2h 24/7 cycle — full competitor coverage with no scheduling gaps; 4th verification criterion (Competitor) added"}
{"d":"2026-04-11","t":"FIX","m":"Scraper: CRAWLEE_PURGE_ON_START=1 set in withIsolatedStorage — fixes FS.com + ATGBICS crash on startup (SDK_SESSION_POOL_STATE.json not found in fresh isolated storage dir)"}
{"d":"2026-04-11","t":"FEAT","m":"Scraper: NADDOD, QSFPTEK, AddOn Networks added to pg-boss scheduler (every 2h, slots :48/:52/:55) — 24 pricing queues total, 58 workers"}
{"d":"2026-04-11","t":"FIX","m":"Scraper: ProLabs rewritten from PlaywrightCrawler (blocked by CloudFront WAF TLS fingerprinting) to fetch-based sitemap scraper — catalog-only (B2B quote model, no public prices)"}
{"d":"2026-04-11","t":"FIX","m":"Scraper: startup zombie cleanup in index.ts — on daemon restart, active pg-boss jobs older than 5 min are marked failed to allow re-queueing at next cron tick"}
{"d":"2026-04-11","t":"FIX","m":"Scraper: pre-existing TypeScript build errors fixed (findOrCreateScrapedTransceiver: removed invalid name/url/extractType params; ebay-enricher cheerio type mismatch; community-issues description→summary, publishedDate→published_at)"}
{"d":"2026-04-04","t":"AI","m":"Blog Engine v5: STEP8b replaced with Reduction Engine v1.0 (5-pass: Repetition Kill → Tech Prune → Flow Rebuild → Weight Correction → Humanization); target 700-1000 words; LaTeX hard delete in Pass 2; title/content alignment in Pass 4; word count range enforcement 600-1300 with warnings"}
{"d":"2026-04-04","t":"DATA","m":"Blog calibration: Gold Standard 5 added (market alert / pricing article — 2026-04-04; title matches body throughout; no LaTeX; DR4 = MPO-12 not LC duplex; ending lands on title topic not generic close)"}
{"d":"2026-04-04","t":"AI","m":"Blog Engine v5: system prompt + STEP9 QA hardened with LaTeX hard fail (\\[...\\] destroys flow), DR4 connector hard fail (DR4=MPO-12, FR4=LC duplex), title/content alignment check (12d); WRONG PATTERNS extended with 4 new entries"}
{"d":"2026-04-04","t":"AI","m":"Blog Engine v5: STEP4b Narrative Control (4-correction pass after draft — root cause assignment, anti-FUD filter, reality reframe, Flexoptix voice check); minimum words 1500→2500; reduction pass 25-35%→15-25%; pipeline now 14 steps, version v5-narrative-control"}
{"d":"2026-04-04","t":"AI","m":"Blog Engine v5: STEP_LINKEDIN_POST — generates LinkedIn post ≤2800 chars from final article (hook + 3-5 insights + CTA + hashtags); stored in blog_drafts.linkedin_post + linkedin_char_count; hard truncation at 2800 if LLM exceeds limit"}
{"d":"2026-04-04","t":"DATA","m":"Blog calibration: Gold Standard 4 added (compatible vs OEM narrative correction — 2026-04-04; optic = not root problem, exposes existing issues; correct Flexoptix framing: validation responsibility shifts to operator)"}
{"d":"2026-04-04","t":"DATA","m":"Migration 024: linkedin_post + linkedin_char_count columns in blog_drafts"}
{"d":"2026-04-04","t":"FIX","m":"Proxy Network: IP geo-lookup via ip-api.com on register/heartbeat (country_code + city now populated); heartbeat_count column + uptime_pct computed per heartbeat (was always 0.00); dedup fix — register returns existing token for same IP+port; heartbeat no longer overwrites registered IP (prevented IPv6 churn conflicts)"}
{"d":"2026-04-04","t":"DATA","m":"Proxy Network: migration 023 — heartbeat_count column added, existing node uptime_pct backfilled, duplicate registration from same IPv6 removed (4 nodes → 3)"}
{"d":"2026-04-04","t":"AI","m":"Blog Engine v4: STEP8b Reduction Pass (25-35% content cut, removes repeated concepts) + STEP8c Style Lock (tone consistency, scope/OPM fix, no inline SKUs) — pipeline now 12 steps, version v4-reduction-stylelock"}
{"d":"2026-04-04","t":"DATA","m":"Blog calibration: Gold Standard 3 added (Style B troubleshooting — 2026-04-04 field feedback, flowing narrative, zero sections, failure as behavior not scenario)"}
{"d":"2026-04-04","t":"FIX","m":"Flexoptix scraper: contentHash call fixed (was passing JSON.stringify string, now passes object directly)"}
{"d":"2026-04-03","t":"FEAT","m":"TIP Proxy Network (packages/proxy-agent): SOCKS5 residential proxy for CloudFront WAF bypass — node registration, heartbeat, load balancing with uptime+latency scoring"}
{"d":"2026-04-03","t":"FEAT","m":"proxy-agent CLI package (@tip/proxy-agent): tip-agent start/status/stop, configurable bandwidth cap, 30s heartbeat, graceful shutdown"}
{"d":"2026-04-03","t":"FIX","m":"DB utils: price_verified=true now set in content_hash early-return path (no new observation); image_verified=true auto-set on INSERT and on image_url update in findOrCreateScrapedTransceiver"}
{"d":"2026-04-03","t":"FIX","m":"pg-boss pool: max connections reduced to 4 + idle_in_transaction_session_timeout=30s — fixed PostgreSQL max_connections exceeded (100/100)"}
{"d":"2026-04-03","t":"DATA","m":"Image backfill: 178 Flexoptix images added via GraphQL small_image — Optcore images via Playwright gallery — findOrCreateScrapedTransceiver now updates image_url for existing records"}
{"d":"2026-04-03","t":"FEAT","m":"SmartOptics scraper: DWDM/coherent product catalog, og:image extraction, 8 products with form factor + reach detection"}
{"d":"2026-04-03","t":"FIX","m":"Fluxlight scraper: price extraction fixed for BigCommerce HTML (data-product-price-without-tax attribute)"}
{"d":"2026-04-03","t":"AI","m":"Blog Engine v3: STEP4 prose requirement (zero tolerance for ## headers, #### Scenario: patterns, bullet sections) — STEP3 outline as flow plan (3-4 beats) — STEP9 format violations as primary hard fail"}
{"d":"2026-04-03","t":"FIX","m":"Blog engine: DR4 wavelength corrected to 1310nm=0.35dB/km; scope description fixed (visual tool, not loss measurement device)"}
{"d":"2026-04-03","t":"FIX","m":"Blog engine: orphaned floating text in fo-blog-pipeline.ts removed (dead code outside template literal causing TypeScript build failure)"}
{"d":"2026-04-03","t":"FEAT","m":"NOG Talks scraper: DENOG/NANOG/RIPE/ENOG/NLNOG/Euro-IX conference talks — relevance scoring, optical keyword detection, weekly pg-boss job, CtxEvent cross-DB bridge via dblink"}
{"d":"2026-04-03","t":"FEAT","m":"Hot Topics v2: market_intelligence as SOURCE 3b (0.6+ relevance, urgency mapping per intel_type), NOG Talks as SOURCE 3c (grouped by event with speaker+abstract), limit 20 topics"}
{"d":"2026-04-03","t":"FIX","m":"Flexoptix scraper: 1G SFP coverage fixed (added SFP LX/SX/ZX queries); SKU suffix stripping (:Sx → base SKU); pagination cap removed (200-product limit was blocking full catalog); Phase 1→2 URL enrichment"}
{"d":"2026-04-03","t":"FEAT","m":"Prediction intelligence fully_verified trigger: PostgreSQL trigger trg_sync_fully_verified auto-computes fully_verified = price_verified AND image_verified AND details_verified — mass backfill: 258 → 3615 badges"}
{"d":"2026-04-02","t":"FEAT","m":"Auth: password-protected login page — HMAC-SHA256 signed token, requireAuth middleware on all API routes, dark TIP-themed login page"}
{"d":"2026-04-02","t":"INFRA","m":"Raspberry Pi fleet: 3x Pi nodes running 24/7 as lightweight scraper workers via WireGuard VPN, pg-boss multi-node queue sharing"}
{"d":"2026-04-02","t":"INFRA","m":"WireGuard VPN: Pi fleet tunnel for secure PostgreSQL access to production DB"}
{"d":"2026-04-02","t":"FEAT","m":"Prediction Intelligence System (migration 022): 7 new tables — hyperscaler_capex, distributor_lead_times, github_tech_signals, marketplace_velocity, ai_cluster_announcements, standards_activity, forecast_signals"}
{"d":"2026-04-02","t":"FEAT","m":"SEC EDGAR scraper: XBRL API, quarterly CapEx for Amazon/Microsoft/Alphabet/Meta — DC-share estimate + YoY growth"}
{"d":"2026-04-02","t":"FEAT","m":"GitHub Signals scraper: weekly repo_count/commit/stars for 400G/800G/ZR/CMIS/CPO/silicon-photonics tech adoption tracking"}
{"d":"2026-04-02","t":"FEAT","m":"eBay Velocity scraper: sold/active listing counts + avg price for 9 transceiver search terms — every 12h"}
{"d":"2026-04-02","t":"FEAT","m":"AI Cluster Announcements scraper: 6 RSS feeds (DataCenterKnowledge, DC Dynamics, Blocks&Files, Next Platform, ServeTheHome) — extracts company, MW, network speed, estimated transceivers"}
{"d":"2026-04-02","t":"FEAT","m":"Distributor Lead Times scraper: Mouser, Digi-Key, RS Components — in_stock, stock_qty, lead_time_weeks, price — daily"}
{"d":"2026-04-02","t":"FEAT","m":"Standards Tracker: IEEE 802.3 project table, OIF hot topics, IETF Datatracker API — tracks in-progress/ballot/published status — weekly"}
{"d":"2026-04-02","t":"FEAT","m":"Forecast Engine: weighted demand index (0-100) from 6 signal types — capex 0.30, ai_clusters 0.25, ebay_velocity 0.20, lead_times 0.15, github 0.06, standards 0.04 — 3/9/12/18 month horizons for 5 technologies"}
{"d":"2026-04-02","t":"FEAT","m":"NAS sync: datasheet/manual download — PDFs from product_documents organized into switches/transceivers/whitepapers/other"}
{"d":"2026-04-02","t":"INFRA","m":"Scheduler: 50 total pg-boss jobs — 8 new prediction/forecast jobs with cron schedules"}
{"d":"2026-04-03","t":"FEAT","m":"TIP Proxy Network: residential proxy pool — contributor nodes donate bandwidth, SOCKS5 server (Node.js net only), register/heartbeat/next/rotate/stats API, round-robin routing with uptime+latency scoring"}
{"d":"2026-04-03","t":"FEAT","m":"@tip/proxy-agent: standalone CLI package — tip-agent start/status/stop, configurable bandwidth cap, 30s heartbeat, graceful shutdown"}
{"d":"2026-04-03","t":"UI","m":"Dashboard Network tab: node stats, join-the-network card with token generator, install command box, country breakdown table"}
{"d":"2026-04-03","t":"INFRA","m":"Mac Studio home node: tip-agent running on 192.168.178.213:1081, PROXY_URL=socks5://192.168.178.213:1081 set in PM2 env for scraper+api, ProLabs WAF bypass now active"}
{"d":"2026-04-01","t":"FEAT","m":"Product Intelligence Layer (migration 020): product_issues table (forum/community bugs), condition+marketplace on price_observations, features JSONB on switches+transceivers"}
{"d":"2026-04-01","t":"FEAT","m":"eBay Enricher: scrapes eBay.de for switch/transceiver listings — extracts features, description, refurbished prices, images — nightly via pg-boss"}
{"d":"2026-04-01","t":"FEAT","m":"Community Issues Scraper: extracts known bugs/incompatibilities from Reddit, ServeTheHome, Arista Community, Cisco Community, NetworkEngineering SE"}
{"d":"2026-04-01","t":"DATA","m":"7 pre-seeded community issues: Arista QSFP28 EOS compatibility, Cisco SFP DOM bug, Juniper QFX5120 config tip, SG350 SFP speed limit, MikroTik CRS326 QoS, DCS-7800R3 QSA, UniFi third-party warning"}
{"d":"2026-04-01","t":"FEAT","m":"API: GET /api/switches/:id/issues — known community issues with severity, tags, source links; GET /api/switches/:id/documents — official datasheets+manuals"}
{"d":"2026-04-01","t":"UI","m":"Switch detail modal: shows features array from DB, description, eBay refurbished price, known issues with severity color coding, datasheets with download links"}
{"d":"2026-04-01","t":"FEAT","m":"Datasheet Finder: discovers and links official PDF datasheets/manuals from vendor sites (Arista, Cisco, Juniper, HPE) for existing switches"}
{"d":"2026-04-01","t":"DATA","m":"SMB/campus switch seed: 26 models across Cisco SG/CBS 350/550/CBS350, HPE Aruba 1820/2530/2930F, Ubiquiti UniFi Pro/Aggregation, MikroTik CRS326/354/504, Netgear M4300/M4500, Zyxel XGS"}
{"d":"2026-04-01","t":"FIX","m":"forecast.ts: fixed fiveYearProjection accessor (hype.forecast.fiveYearProjection[n] instead of hype.forecast[n])"}
{"d":"2026-04-01","t":"FEAT","m":"Procurement Intelligence Engine: stock_snapshots, abc_classification, reorder_signals, product_lifecycle_events, market_intelligence tables"}
{"d":"2026-04-01","t":"FEAT","m":"Crawler LLM: Ollama-based two-stage extractor (page type detection + structured product extraction) with vendor profiles for 7 vendors"}
{"d":"2026-04-01","t":"FEAT","m":"ABC classification: dynamic A/B/C turnover scoring from price observations, compatibility breadth, vendor count — computed daily"}
{"d":"2026-04-01","t":"FEAT","m":"Reorder signals: buy_now/wait/hold/monitor with signal strength and reasons — computed daily from stock trends, price trends, lead times"}
{"d":"2026-04-01","t":"DATA","m":"Market intelligence seeded: OFC 2026, AWS CapEx $105B, Azure CapEx $80B+, Coherent 400G ZR+ lead times 16-20w, EU TED €2.1B tenders, ECOC 2026, IEEE 802.3df"}
{"d":"2026-04-01","t":"DATA","m":"Lifecycle events seeded: Cisco SFP-10G-LR EOL 2026-06-30, Juniper SFPP-10GE-ER EOL 2026-09-01, 400ZR ratified, 800G MSA draft"}
{"d":"2026-04-01","t":"UI","m":"Procurement Intel tab: Reorder Signals, ABC Classes table, Market Intel cards, Lifecycle Events — live on dashboard"}
{"d":"2026-04-01","t":"FEAT","m":"Market intelligence scraper: OFC/ECOC, IEEE 802.3, EU TED, Farnell/Mouser lead times, LightReading, FierceTelecom — weekly via pg-boss"}
{"d":"2026-04-01","t":"FIX","m":"Dashboard: garbage product names (scraped-*, All Optical Transceivers) no longer shown as product titles — isGarbageName() filter"}
{"d":"2026-04-01","t":"FIX","m":"Dashboard: competitor comparable prices shown as inline tooltip (ⓘ) instead of block element breaking price row layout"}
{"d":"2026-04-01","t":"UI","m":"Dashboard: 100% VERIFIED badge with white-on-green sub-items (Price ✓, Image ✓, Details ✓) — explicit === true checks, no false positives"}
{"d":"2026-04-01","t":"UI","m":"Dashboard list view: SKU + descriptive name on two lines, Verified column with ★ 100% badge"}
{"d":"2026-04-01","t":"UI","m":"Dashboard detail view: manufacturer product name above image, temperature range decoded (COM → 070°C), close button visible on light background"}
{"d":"2026-04-01","t":"DATA","m":"Migration 018: garbage data cleanup — marks scraped-* and category-page scrapes as data_confidence=garbage"}
{"d":"2026-04-01","t":"FEAT","m":"Migration 017: verification tags — price_verified, image_verified, details_verified, fully_verified columns + compute_transceiver_verification() function"}
{"d":"2026-03-31","t":"DATA","m":"Migration 016: data_confidence scoring (garbage/low/medium/high)"}
{"d":"2026-03-31","t":"FEAT","m":"Migration 013: v0.2.0 Sales Intelligence tables — competitor_alerts, price_changes, generated_datasheets, sales_forecasts, blog_posts_v2"}
{"d":"2026-03-31","t":"FEAT","m":"Transport planner route: GET /api/transport — city-pair fiber route recommendations with switch and transceiver BOM"}
{"d":"2026-03-31","t":"FEAT","m":"Blog Engine v2: market_alert, migration_guide, competitor_analysis, buying_guide types with data enrichment pipeline"}
{"d":"2026-03-31","t":"FEAT","m":"Competitor alerts route: GET /api/competitor-alerts — price changes, new products, stock events with acknowledge workflow"}
{"d":"2026-03-30","t":"FEAT","m":"Switch→Flexoptix Finder: GET /api/finder — enter switch model, get matching Flexoptix transceivers with prices and shop links"}
{"d":"2026-03-30","t":"FEAT","m":"MCP Server: 12 tools including find_transceiver, get_compatibility, get_hype_cycle, generate_blog, plan_transport"}
{"d":"2026-03-30","t":"FEAT","m":"Norton-Bass Hype Cycle engine: multigenerational diffusion model for 15 transceiver technologies with adoption curves"}
{"d":"2026-03-30","t":"DATA","m":"440 switches seeded including Cisco, Arista, Juniper, Edgecore, Mellanox, whitebox OCP switches"}
{"d":"2026-03-30","t":"DATA","m":"33,993 compatibility entries — transceiver↔switch compatibility matrix"}
{"d":"2026-03-30","t":"FEAT","m":"Price monitoring: 23 scrapers, 60+ data sources, pg-boss scheduler — permanent monitoring"}
{"d":"2026-03-30","t":"FEAT","m":"Qdrant vector DB integration: hybrid full-text + semantic search across products, FAQ, datasheets, news"}
{"d":"2026-03-30","t":"INFRA","m":"Stack deployed: PostgreSQL 17 + TimescaleDB, Qdrant, Cloudflare R2 for images, PM2"}
{"d":"2026-03-30","t":"DATA","m":"v0.1.0: 5,018 transceivers, 351 vendors seeded from 23 initial scrapers"}
{"d":"2026-04-17","t":"DATA","m":"Vendor cleanup: pruned 242 irrelevant OEM/manufacturer vendors with no transceiver or switch data — 348→106 vendors"}
{"d":"2026-04-18","t":"FEAT","m":"Mouser Electronics API scraper: OEM reference prices for Juniper/Cisco/Arista PIDs — scheduled daily 03:00, MOUSER_API_KEY env var required"}
{"d":"2026-04-18","t":"FEAT","m":"Hype Cycle Engine: Norton-Bass diffusion model fitted to 6 tech generations (10G/100G/400G-QSFP-DD/800G-OSFP/400G-ZR/1.6T). Bass params via grid search, Gartner phase detection, ASP log-linear projection. Seeded market_metrics + hype_cycle_analysis table. Scheduled daily 04:30. API: GET /api/hype-cycle/analysis"}
{"d":"2026-04-18","t":"DATA","m":"migration 039: hype_cycle_analysis table (Bass p/q/M params, phase, score, projected share 1y/3y, ASP current + decline %). market_metrics CHECK extended with hype_score type"}
{"d":"2026-04-20","t":"FEAT","m":"switch-image-fetcher.ts: og:image-based image discovery for all 86 seeded switches — covers Cisco, Arista, Juniper, NVIDIA, Edgecore, Celestica, Asterfusion, Dell, HPE, Huawei, Nokia, Extreme, MikroTik, Ubiquiti, FS.COM, Supermicro. Daily at 08:30 UTC."}
{"d":"2026-04-20","t":"FEAT","m":"flexoptix-compat.ts: Flexoptix compatibility scraper — maps switch models to compatible Flexoptix transceivers via search API (vendor_compat) with form-factor fallback (spec_match). Daily 09:00 UTC."}
{"d":"2026-04-20","t":"FEAT","m":"community-issues.ts enhanced: added Cisco Field Notices, Juniper KB, SONiC GitHub Issues sources + new scrapeTransceiverCompatIssues() for switch+transceiver combo issues."}
{"d":"2026-04-20","t":"UI","m":"Dashboard switch table: thumbnail column (48px lazy-load image with gear-icon fallback). Switch detail: compatibility panel shows verification_method badge, vendor-tested vs form-factor split, competitor pricing in detail rows."}
{"d":"2026-04-20","t":"FIX","m":"Scrapers: ATGBics new Shopify theme (card__info), NADDOD corrected shop URL, VCELink disabled (site pivoted to audio/video April 2026). Scheduler: 59 schedules, 78 workers."}
{"d":"2026-04-21","t":"FEAT","m":"switch-image-playwright.ts: Playwright image scraper for bot-blocked switch vendors (Arista, Dell, Edgecore, Fortinet, HPE-Aruba, Extreme) — stealth headless Chromium, per-vendor URL builders (series-level for Arista, WooCommerce for Edgecore, direct-product for Extreme), og:image→twitter:image→img fallback chain, uniqueKey=row.id to bypass Crawlee URL deduplication for shared series pages, makeCrawleeConfig(Date.now() suffix) per-run to avoid ENOENT from stale request-queue files."}
{"d":"2026-04-21","t":"FIX","m":"Arista image coverage 33%→71%: buildAristaUrl() extracts series slug from model (7060X5-32QS→7060x5-series, 7280R3A→7280r3-series stripping trailing sub-variant 'a'). uniqueKey=row.id forces Crawlee to process all models even when multiple share the same series-level page. 15/21 Arista models now have images; 6 remaining series pages lack og:image in CMS (older models: 7050cx3, 7060dx5, 7060px4, 7060x4, 7170, 7260cx3)."}
{"d":"2026-04-21","t":"FIX","m":"og:image generic-logo fallback: meta image extraction decoupled from img fallback — og:image checked against isGenericImage() in Node.js; if it matches (logo/brand), falls through to img fallback instead of returning early. Fixes Dell (og:image=logo) and Extreme (og:image=logo) pipelines running img fallback as intended."}
{"d":"2026-04-21","t":"FIX","m":"OneTrust/cookie consent image filter: cdn.cookielaw.org, cookiebot.com, trustarc.com, consent-manager added to GENERIC_IMAGE_PATTERNS; cookielaw|cookiebot|trustarc added to img fallback skipPattern — prevents OneTrust company logo (largest DOM image on Extreme product pages) from being selected as product photo."}
{"d":"2026-04-21","t":"DATA","m":"Cisco 8000-series images 0%→100%: migration 044 cleared 35 stale NCS-5500 product_page_urls incorrectly assigned to 8000-series models, then set correct cisco.com/site/us/en/ URLs. switch-image-fetcher.ts plain HTTP run: 32/32 Cisco 8000-series models now have images."}
{"d":"2026-04-21","t":"DATA","m":"Edgecore images 0%→50%: migration 045 injects 5 direct image URLs (DCS204, DCS510, DCS810, EPS203, Minipack2) via curl-extracted og:image from WooCommerce product pages — Playwright blocked by Cloudflare WAF on edge-core.com but plain curl succeeds. AS7xxx enterprise switches not listed on edge-core.com website."}
{"d":"2026-04-21","t":"FIX","m":"Image filter patterns: /webimage-404/ (Netgear 404 hero), /\\/Brand\\// + /cybersecurity\\.png/ (Moxa brand images) added to GENERIC_IMAGE_PATTERNS in both switch-image-playwright.ts and switch-image-fetcher.ts. Cleared 5 bad DB rows (Moxa Brand/cybersecurity.png x4, Netgear webimage-404 x1)."}
{"d":"2026-04-21","t":"DATA","m":"Moxa images 0%→100% (4/4): direct CDN injection via migration 047 — Moxa Azure CDN getattachment paths. Hotlink-protected (Referer: moxa.com required); R2 proxy needed for production display."}
{"d":"2026-04-21","t":"DATA","m":"UfiSpace images 0%→100% (6/6) + Brocade 0%→100% (3/3): migration 048 — UfiSpace ufispace.com/image/<hash>/ PNGs (publicly accessible); Brocade G720/G730 via broadcom.com og:image, ICX 7850-48FS via CommScope/Ruckus vistancenetworks.com ImageServer (rand param cache-bust only, ID hash stable)."}
{"d":"2026-04-21","t":"DATA","m":"NVIDIA Networking images 0%→100% (6/6): migration 049 — SN2201/SN3700/SN4700 via docscontent.nvidia.com official docs CDN, SN5400/SN5600 via k3-prod-nvidia-docs.s3 direct, SN3750-SX via uvation reseller CDN."}
{"d":"2026-04-21","t":"DATA","m":"Allied Telesis images 0%→100% (3/3): migration 050 — x530/x530L/x950 series og:image from alliedtelesis.com Drupal CMS static files. QCT T3048-LY8 image via migration 046. Overall coverage: 33.4%→36.2%+ across 671 switches."}
{"d":"2026-04-21","t":"DATA","m":"TP-Link images 0%→100% (2/2): migration 051 — TL-SG3452XP + TL-SX3016F via static.tp-link.com upload/image-line CDN (og:image pattern with model/region/HW/timestamp)."}
{"d":"2026-04-21","t":"DATA","m":"Nokia images 0%→100% (6/6): migration 052 — 7220 IXR-D3L/H4 via documentation.nokia.com SR Linux docs graphics; 7250 IXR-10 + 7750 SR-1 via tempestns.com model-specific reseller CDN; 7750 SR-14s via telecomcauliffe.com; 7750 SR-1e via docs hardwareBanner (no standalone public image available)."}
{"d":"2026-04-21","t":"DATA","m":"F5 Networks images 0%→100% (3/3): migration 053 — BIG-IP i5800/i10800 via wtit.com reseller CDN (model-specific PNGs), i15800 via cdn.blueally.com bigip-i15000-series composite."}
{"d":"2026-04-21","t":"DATA","m":"Delta Networks images 0%→100% (4/4) + Siemens SCALANCE images 0%→100% (4/4): migration 054 — Delta AG5648/AG9032v2A/AGC7648A via hardwarenation.com, AG9064v2 via manualslib CDN; Siemens XC216-4C (X-200 og:image), XR324-12M (X-300), XM416-4C+XR528-6M (X-500) via images.sw.cdn.siemens.com official DISW CDN."}
{"d":"2026-04-21","t":"DATA","m":"MikroTik CRS/CCR images (8 models) + NVIDIA ConnectX-7 400G: migration 055 — all MikroTik via cdn.mikrotik.com/web-assets/rb_images (CRS305/312/317/326/354/504/518 + CCR2216); ConnectX-7 via FS.com CDN. MikroTik now 100%."}
{"d":"2026-04-21","t":"DATA","m":"ALE OmniSwitch 0%→100% (3/3) + H3C 0%→100% (3/3) + Hirschmann 0%→100% (4/4) + Ciena 0%→100% (3/3) + Netberg 0%→100% (3/3): migration 056 — ALE via al-enterprise.com CDN, H3C via resource.h3c.com, Hirschmann via industrialcomms.com/icomtechinc, Ciena via ciena.com/__data, Netberg via netbergtw.com."}
{"d":"2026-04-21","t":"DATA","m":"Arista Networks new series images (6 models) + Edgecore AS-series 3 models: migration 057 — 7060X6/X5/7050X4/7280R3/7020R via arista.com CDN; AS7726(=DCS204)/AS9516(=DCS810)/AS7535(=CSR440) via edge-core.com WP uploads."}
{"d":"2026-04-21","t":"DATA","m":"Fortinet FortiSwitch 0%→100% (11/11) + Dell PowerSwitch (3) + Huawei (4): migration 058 — FortiSwitch 108F/124F/124F-POE/148F-POE/424E/448E/524D/548D/1024E/1048E/3032E via cdn.blueally.com/avfirewalls; Dell Z9332F/S5248F via i.dell.com CDN, Z9664F via reseller; Huawei S5731 via e.huawei.com og:image."}
{"d":"2026-04-21","t":"DATA","m":"D-Link 0%→100% (3/3) + Netgear 0%→100% (3/3) + Check Point 0%→100% (2/2) + Ruckus 0%→100% (2/2): migration 059 — D-Link via dlink.com media CDN; Netgear via assets.netgear.com + blueally CDN; Check Point via tecisoft.ca + blueally; Ruckus ICX via productresources.vistancenetworks.com."}
{"d":"2026-04-21","t":"DATA","m":"HPE Aruba CX 0%→100% (3/3) + Extreme Networks 0%→100% (3/3): migration 060 — Aruba CX 10000/9300/6300 via bigcommerce/kaseya/avendor CDNs; Extreme SLX 9740-40C + X695-48Y-8C + 5520-48T via extr-p-001.sitecorecontenthub.cloud (official Extreme CDN)."}
{"d":"2026-04-21","t":"DATA","m":"Cambium cnMatrix EX2028-P+EX2052-P + Gigamon GigaVUE-HC3+HC1-Plus + SonicWall NSa 6700 + Planet Technology GS-6322-24P4X+IGS-6325-8T8S4X + Palo Alto PA-3430/5430/7080 (series images) + Westermo Lynx 5612+Redfox 5728 + Zyxel XGS4600-52F+XS3800-28: migration 061. 14 models, 7 vendors, all official CDNs verified HTTP 200."}
{"d":"2026-04-21","t":"DATA","m":"Synology SA6400 + TRENDnet TPE-5048WS + Waystream ASR 8000 + Kemp Technologies LoadMaster LM-X40 + LANCOM Systems GS-4554XP: migration 062. 5 models, all official vendor CDNs verified HTTP 200."}
{"d":"2026-04-21","t":"DATA","m":"Sophos XGS 6500 via Contentstack CDN (images.contentstack.io, explicit '6500' filename, HTTP 200) + Zyxel XS3800-28 URL fix (migration 061 path returned 403; replaced with Banner_product_hero.png, HTTP 200): migration 063."}
{"d":"2026-04-26","t":"FIX","m":"Umami credentials — PM2 env cache invalidated via delete+start (not --update-env); 500 sessions now loading correctly in Beste Posting-Zeit."}
{"d":"2026-04-26","t":"FIX","m":"Local Train API: changed execFileAsync from sh -lc to bash [script] [lane] to avoid Ubuntu dash syntax errors; added try-catch to return JSON on non-zero exit instead of HTTP 500."}
{"d":"2026-04-26","t":"FIX","m":"Local Train dashboard: disabled buttons when TIP_LOCAL_TRAIN_COMMAND not configured; early-exit guard with setup instructions shown in log area."}
{"d":"2026-04-26","t":"FIX","m":"Build Pool npm script missing on Erik — synced package.json + tip-learning-pool-build.ts; npm run learning-pool:build now works."}
{"d":"2026-04-26","t":"FIX","m":"TIP_LLM 0 pairs on Erik — git reset --hard origin/main restored 10654 train pairs from Gitea."}
{"d":"2026-04-26","t":"FIX","m":"HuggingFace publish — installed huggingface_hub + datasets via pip3 --break-system-packages on Erik; HF_TOKEN added to ecosystem.config.js."}
{"d":"2026-04-26","t":"AI","m":"TIP_LLM 5-capability system prompt: CAP-1 Transceiver Research, CAP-2 Switch Research, CAP-3 Blog_LLM Data Evaluation, CAP-4 Crawler/Scraper Design, CAP-5 Hype Cycle Calculation — replaces single-line generic prompt."}
{"d":"2026-04-26","t":"DATA","m":"TIP_LLM capabilities training data: seed-tip-llm-capabilities.ts generates 34 SFT pairs (149KB) covering all 5 CAPs with real product names, Crawlee code, Norton-Bass model examples, scoring rubrics. Registered in tip-learning-pool-build.ts."}
{"d":"2026-04-26","t":"DATA","m":"TIP_LLM training pool rebuilt: 12141 raw pairs → 11872 training pairs (10684 train + 1188 eval). Published to HuggingFace renefichtmueller/tip-llm-sft. Blog_LLM: 11408 pairs published to renefichtmueller/blog-llm-sft."}
{"d":"2026-04-21","t":"DATA","m":"Avaya VSP 7432CQ + NetApp CN1610 + Keysight Vision X + A10 Networks Thunder 14045 + Evertz EXE-VSR-IP + RAD ETX-2i-10G + Ekinops 360-12 + DrayTek VigorSwitch P2540xs + Fujitsu FLASHWAVE 9500 + Broadcom BCM957508-P2100G + Calix E9-2 + Citrix NetScaler SDX 26000-100G: migration 064. 12 models, all HTTP 200 verified (mix of official CDNs and reseller CDNs)."}
{"d":"2026-04-21","t":"DATA","m":"Cisco 8000/Catalyst 9000/Nexus 9000/NCS (14 models) via cisco.com/c/dam/en/us/td/i/ doc CDN: migration 065. All HTTP 200 verified."}
{"d":"2026-04-21","t":"DATA","m":"Juniper EX4100-48P/EX4400-48T/EX4650-48Y + MX10008/MX304 + QFX10008/5120/5130/5220/5700 (10 models) via juniper.net/content/dam/image-library: migration 066. All HTTP 200 verified."}
{"d":"2026-04-21","t":"DATA","m":"Arista 7020R/7050CX3-32S/7050X4-32/7060DX5-32/7060PX4-32/7060X4-32/7060X5-64/7130-48/7170-64C/7260CX3-64/7800R3-36P-LC (11 models) via arista.com QSG CDN front-panel PNGs: migration 067. All HTTP 200 verified."}
{"d":"2026-04-21","t":"DATA","m":"NVIDIA Networking SN2201/SN3700/SN4700/SN5400/SN5600 (5 models) via docscontent.nvidia.com dims4 CDN (Hardware User Manual front-panel images): migration 068. All HTTP 200 verified."}
{"d":"2026-04-21","t":"DATA","m":"Huawei CE16808/CE6866-48S8CQ/CE8851-32CQ8DQ/NE40E-X8A/S5735-L48T4X-A (5 models via ycict.net WP CDN) + Nokia 7220 IXR-D3L (documentation.nokia.com) + Nokia 7750 SR-14s (telecomcauliffe.com SR series): migration 069. 7 models, all HTTP 200 verified."}
{"d":"2026-04-21","t":"DATA","m":"Dell N3248TE-ON (networktigers) + S5248F-ON/S5296F-ON (i.dell.com Scene7 CDN) + Z9332F-ON/Z9664F-ON (expresscomputersystems Shopify) + Extreme Networks 8720-32C+X465-48P (sitecorecontenthub.cloud official CDN): migration 070. 7 models, all HTTP 200 verified."}
{"d":"2026-04-21","t":"DATA","m":"HPE Aruba CX 6300M-48G/8100-48Y6C/8360-32Y4C (blueally.com partner CDN) + Ubiquiti USW-EnterpriseXG-24/Pro-Aggregation/Pro-Max-48-PoE (cdn.ecomm.ui.com official) + Supermicro SSE-C4632SRB/SSE-T7132SR (wiredzone.com): migration 071. 8 models, all HTTP 200 verified."}
{"d":"2026-04-21","t":"DATA","m":"Celestica DS3000/DS4000/DS5000 (foleon.com Celestica CDN) + Asterfusion CX308P-48Y-N/CX532P-N/CX864E-N (asterfusion.com WP + cloudswit.ch) + FS.com N8560-32C/S5860-48SC (resource.fs.com) + Edgecore DCS810/EPS203 (edge-core.com WP): migration 072. 10 models, all HTTP 200 verified."}
{"d":"2026-04-26","t":"DATA","m":"OEM seed scrapers batch 1-20: keysight(25), sycamore(17), ekinops(18), adva(19), coriant(17), casa-systems(22), harmonic(23), solarflare(25), marvell(26), broadcom(23), calix-access(20), ribbon-comms(20), infinera-groove(20), ciena-waveserver(22), commscope(20), teleste(19), tejas-networks(19), ericsson-transport(20), adtran-ta(20), isolan(18). Scheduler daily 20:00-00:45."}
{"d":"2026-04-26","t":"DATA","m":"OEM seed scrapers batch 21-40: telco-systems(18), rad(20), comtrend(18), packetfront(18), edgewater-networks(16), corning(18), ofs(18), kontron(18), ipinfusion(18), telrad(16), siklu(16), ceragon(16), datang(16), viptela(16), versa-networks(16), vmware(16), cimc(18), qlogic(20), emulex(18), netapp(20). Scheduler daily 01:00-05:45."}
{"d":"2026-04-26","t":"DATA","m":"OEM seed scrapers batch 41-60: pure-storage(16), hpe-storage(20), ibm-storage(20), dell-storage(18), hitachi-vantara(16), aws(16), azure(16), google-cloud(16), meta(16), nokia-access(20), huawei-access(20), zte-access(18), calix-gigapoint(16), samsung-networks(16), nokia-airscale(16), ericsson-ran(16), mavenir(14), ixia(18), exfo-network(18), cumulus-networks(16). Scheduler daily 06:00-10:45."}
{"d":"2026-04-26","t":"DATA","m":"OEM seed scrapers batch 61-80: sonic(16), h3c(20), ruijie(17), centec(16), supermicro(18), cisco-meraki(18), cisco-catalyst(20), cisco-nexus(20), cisco-asr(20), juniper-mx(20), juniper-qfx(20), aruba-cx(18), extreme-campus(18), arista-7000(20), pica8(16), pluribus(14), drivenets(15), phoenix-contact(18), beckhoff(16), omron(16). Scheduler daily 11:00-15:45."}
{"d":"2026-04-26","t":"DATA","m":"OEM seed scrapers batch 81-84: abb(16), siemens-scalance(18), schneider(16), rockwell(16), belden(16). Industrial category. Scheduler daily 16:00-17:00."}
{"d":"2026-04-26","t":"FEAT","m":"tip-llm-guided.ts: Structured inference engine for tip-llm-v1. Hard JSON schema, per-field validation, 2-retry repair loop with diff prompt, safe default fallback (create_finding=false). Temperature 0.1→0.05 on retry. Routes: POST /api/tip-llm/infer|research-plan|extract|finding, GET /api/tip-llm/health."}
{"d":"2026-04-28","t":"FIX","m":"Product verification pipeline: image crawls now mark image_verified/image_verified_url, scraped product pages mark details_verified/details_source_url, maintenance reconcile backfills old product URLs/images/details, and --backfill-images exposes the existing image crawler via scraper CLI. Migration 102 reconciles existing data."}
{"d":"2026-04-28","t":"FIX","m":"Blog Engine Hot Topics: diversified ranking with refresh shuffle/source caps/already-created-topic demotion, plus richer LLM context briefings passed into topic expansion and master-draft context via custom_title/additional_context."}
{"d":"2026-04-29","t":"FEAT","m":"TIPLLM robot learning loop: verification robot controller writes status, TIPLLM plans, queue dry-runs/enqueues and crawler outcomes into the Gitea-backed TIP training pool; learning-pool build imports qa-pairs from TIP_TRAINING_REPO into the tip_llm lane. Removed hardcoded Gitea token fallback; existing git remotes or env tokens are used."}