================================================================================
RE-QA — Redmine #21 (epic) — Enhance Matching Results & AI Assistant
        with Company Enrichment and Market Insights
Projet : GetYourJob (id 11)   PR #239 (base dev)   branche feat/redmine-21-insights-ui
Commit du correctif : 549534e  (fix i18n collision marketInsights)
Date : 2026-06-11        Statut entrant : In development -> draggé en QA avant tests
================================================================================
OBJET DE LA RE-QA
  Vérifier que la régression i18n bloquante (collision de clé top-level
  `marketInsights:` introduite par #66) est levée, ET que les 3 surfaces de
  l'épic restent fonctionnelles (#64 carte entreprise, #66 section Tendances,
  #67 assistant). Déclencheur d'échec dur : NO-FAKE-DATA.

ENVIRONNEMENT
  Worktree : .worktrees/redmine-21-insights-ui (node_modules + .env présents)
  npx prisma generate : OK
  DB Postgres port 5436 : UP
  App dev : npm run dev -- -p 3013 (Next.js 16.0.10 Turbopack, Ready)
  (toutes les valeurs sensibles — env/clés/tokens/DB URL — filtrées de ce rapport)

--------------------------------------------------------------------------------
AC1 — RÉGRESSION i18n CORRIGÉE (le bloqueur)   ===> OK
--------------------------------------------------------------------------------
1a. Exactement UNE clé top-level `marketInsights:` par fichier de locale :
    en.ts -> ligne 2771 (page Statistiques)  + marketInsightsSection: l.3114 (#66)
    fr.ts -> ligne 2780 (page Statistiques)  + marketInsightsSection: l.3123 (#66)
    Le nouveau bloc #66 est bien renommé `marketInsightsSection:` (plus de doublon).

1b. tsc --noEmit — TS1117 dans en.ts / fr.ts :
    grep "translations/(en|fr).ts" sur la sortie tsc => ZÉRO erreur.
    Seul TS1117 restant : src/scripts/cron-geocode-jobs.ts(66,9) — fichier
    NON touché par cette branche (pré-existant, hors scope). Confirmé via
    `git diff --name-only de4b286~1 HEAD` (cron-geocode absent du diff).

1c. Résolution runtime des deux namespaces (import { en, fr } from '../index') :
    EN marketInsights.title          = "Market Statistics"     (page restaurée)
    EN marketInsights.tabs           = object  (n'est plus undefined)
    EN marketInsights.kpi            = object  (n'est plus undefined)
    EN marketInsights.compensation   = object  (n'est plus undefined)
    FR marketInsights.title          = "Statistiques Marché"   (page restaurée)
    FR marketInsights.tabs           = object
    FR marketInsights.kpi            = object
    EN marketInsightsSection.title   = "Market insights"       (distinct)
    FR marketInsightsSection.title   = "Tendances du marche"   (distinct)
    => section != page : les deux namespaces résolvent séparément.

1d. Test garde-fou (anti-récidive) :
    src/infrastructure/i18n/translations/__tests__/marketInsights-namespaces.test.ts
    => 5 tests PASS.

1e. Rendu LIVE de la page précédemment cassée
    /profile/developer/market-insights (port 3013) :
    - En-tête rendu : "Statistiques Marché" (libellé résolu, PAS la clé brute
      `marketInsights.title`, PAS "undefined"), sous-titre + état de chargement
      "Analyse du marché en cours...".
    - Nav latérale : "Statistiques Marché" sous "Insights".
    - Aucune clé brute `marketInsights.*` / `marketInsightsSection.*` ne fuit
      dans le texte de la page (grep sur le DOM => NONE).
    - Console navigateur : aucune erreur i18n / undefined.
    - Page authentifiée au-delà de l'en-tête (OAuth Google/LinkedIn) ; le contenu
      des graphes nécessite un login prod impraticable en QA -> preuve i18n via
      en-tête rendu + test de résolution runtime déterministe.
    Capture : qa-reqa-21-market-statistics-page.png

--------------------------------------------------------------------------------
AC2 — SECTION MARKET INSIGHTS (#66 / #61 / #63)   ===> OK
--------------------------------------------------------------------------------
- MarketInsightsSection.tsx : 100% des t(...) utilisent `marketInsightsSection.*`
  (title, skillsTitle, locationTitle, workModeTitle, offersCount, topLocation,
   workModeShare, loading, error, retry, empty) — aucun `marketInsights.*` nu.
- Sous-blocs : compétences demandées (compteurs réels par offre), localisation
  (phrase tendance), mode de travail (part %). Empty -> EmptyState
  "Aucune tendance disponible..." (jamais de chiffre par défaut). NO-FAKE-DATA OK.
- Suites : MarketInsightsSection.test.tsx (5) + route.test.ts (8) +
  MarketInsightsService.test.ts (11) => PASS.

--------------------------------------------------------------------------------
AC3 — CARTE #64 + ASSISTANT #67 (régression-check)   ===> OK
--------------------------------------------------------------------------------
- #64 CompanyEnrichmentCard.test.tsx (5) PASS : rend seulement les champs
  présents (jamais "N/A"), return null sans enrichment, lien /companies/<slug>.
- #67 SendAssistantMessageUseCase.prompt.test.ts (4) +
  assistantCompanyAndInsights.test.ts (5) PASS : outils get_company_data /
  get_market_insights déclarés + implémentés (present-only, "donnée indisponible"
  sinon agrégat réel), prompt skills>locations + mention type société.

--------------------------------------------------------------------------------
SUITE COMPLÈTE DE L'ÉPIC
--------------------------------------------------------------------------------
npx vitest run (7 suites de l'épic) :
  SendAssistantMessageUseCase.prompt.test.ts ... 4  PASS
  MarketInsightsService.test.ts ............... 11  PASS
  marketInsights-namespaces.test.ts ...........  5  PASS
  route.test.ts (api/market-insights) .........  8  PASS
  MarketInsightsSection.test.tsx ..............  5  PASS
  CompanyEnrichmentCard.test.tsx ..............  5  PASS
  assistantCompanyAndInsights.test.ts .........  5  PASS
  --------------------------------------------------------
  Test Files : 7 passed (7)     Tests : 43 passed (43)

================================================================================
VERDICT : PASS (re-QA)
  - Régression i18n marketInsights : CORRIGÉE (1 seule clé top-level/locale,
    0 TS1117 dans en/fr, page "Statistiques Marché" résout ses libellés).
  - 3 surfaces de l'épic : OK. NO-FAKE-DATA : respecté partout.
  -> #21 LAISSÉ en QA (promotion preprod = autre agent).

PIÈCES JOINTES
  - qa-reqa-21-rapport-technique.txt        (ce rapport)
  - qa-reqa-21-market-statistics-page.png   (page précédemment cassée, en-tête
                                             "Statistiques Marché" résolu)
================================================================================
