{
    "ok": true,
    "generated_at": "2026-07-08T00:10:54+00:00",
    "summary": "Quality gates pour CSV normalises Winerix : schema, output, lignes, en-tetes, source_key et caveat avant import ou publication.",
    "quality_summary": {
        "source_count": 11,
        "qa_ready_count": 3,
        "blocked_count": 8,
        "status_counts": {
            "missing_output": 7,
            "qa_ready": 3,
            "missing_publication_columns": 1
        },
        "next_qa_ready_source": "qualite_tourisme_establishments",
        "top_blocked_source": "sirene_wine_establishments"
    },
    "rows": [
        {
            "source_key": "sirene_wine_establishments",
            "priority": 1,
            "label": "Sirene etablissements vin",
            "status": "missing_output",
            "row_count": 0,
            "output_file": "sources/sirene-wine-establishments-normalized.csv",
            "schema_file": "sources/sirene-wine-establishments-normalized.schema.csv",
            "missing_columns": [
                "source_key",
                "source_row_number",
                "siren",
                "siret",
                "nic",
                "establishment_name",
                "naf_code",
                "naf_label",
                "wine_activity_family",
                "is_active",
                "is_headquarters",
                "creation_date",
                "last_treatment_date",
                "address_raw",
                "postcode",
                "commune",
                "commune_code",
                "department",
                "region",
                "normalized_join_key",
                "publication_scope",
                "caveat"
            ],
            "gates": {
                "schema_exists": true,
                "output_exists": false,
                "has_rows": false,
                "headers_match_schema": false,
                "has_source_key": false,
                "has_caveat": false
            },
            "command": "php scripts/normalize_sirene_wine_establishments.php",
            "next_action": "Executer la normalisation pour produire le CSV cible.",
            "caveat": "Donnees nominatives : RGPD/metier avant listing public."
        },
        {
            "source_key": "ban_address_reference",
            "priority": 2,
            "label": "BAN qualite adresse",
            "status": "missing_output",
            "row_count": 0,
            "output_file": "sources/ban-address-quality.csv",
            "schema_file": "sources/ban-address-quality.schema.csv",
            "missing_columns": [
                "source_key",
                "source_row_number",
                "entity_type",
                "entity_id",
                "entity_name",
                "address_raw",
                "postcode",
                "commune",
                "citycode",
                "ban_label",
                "lon",
                "lat",
                "score",
                "address_score",
                "certified",
                "geocoding_status",
                "address_fingerprint",
                "caveat"
            ],
            "gates": {
                "schema_exists": true,
                "output_exists": false,
                "has_rows": false,
                "headers_match_schema": false,
                "has_source_key": false,
                "has_caveat": false
            },
            "command": "php scripts/normalize_ban_address_quality.php",
            "next_action": "Executer la normalisation pour produire le CSV cible.",
            "caveat": "Adresse geocodee ne prouve pas ouverture au public ni frequentation."
        },
        {
            "source_key": "insee_tourism_occupancy",
            "priority": 3,
            "label": "Insee frequentation hebergements touristiques",
            "status": "missing_output",
            "row_count": 0,
            "output_file": "sources/insee-tourism-occupancy-normalized.csv",
            "schema_file": "sources/insee-tourism-occupancy.schema.csv",
            "missing_columns": [],
            "gates": {
                "schema_exists": true,
                "output_exists": false,
                "has_rows": false,
                "headers_match_schema": false,
                "has_source_key": false,
                "has_caveat": false
            },
            "command": "php scripts/normalize_insee_tourism_occupancy.php",
            "next_action": "Executer la normalisation pour produire le CSV cible.",
            "caveat": "Demande hebergements generale, pas attribution oenotouristique directe."
        },
        {
            "source_key": "qualite_tourisme_establishments",
            "priority": 3,
            "label": "Qualite Tourisme etablissements",
            "status": "qa_ready",
            "row_count": 448,
            "output_file": "sources/qualite-tourisme-establishments-normalized.csv",
            "schema_file": "sources/qualite-tourisme-establishments.schema.csv",
            "missing_columns": [],
            "gates": {
                "schema_exists": true,
                "output_exists": true,
                "has_rows": true,
                "headers_match_schema": true,
                "has_source_key": true,
                "has_caveat": true
            },
            "command": "php scripts/normalize_qualite_tourisme_establishments.php",
            "next_action": "Passer a la revue metier puis import ou hydratation KPI.",
            "caveat": "Label accueil/prestations, pas frequentation ni preuve oenotouristique directe."
        },
        {
            "source_key": "hve_certified_estates",
            "priority": 3,
            "label": "Exploitations certifiees HVE",
            "status": "qa_ready",
            "row_count": 25329,
            "output_file": "sources/hve-certified-estates-normalized.csv",
            "schema_file": "sources/hve-certified-estates-normalized.schema.csv",
            "missing_columns": [],
            "gates": {
                "schema_exists": true,
                "output_exists": true,
                "has_rows": true,
                "headers_match_schema": true,
                "has_source_key": true,
                "has_caveat": true
            },
            "command": "php scripts/normalize_hve_certified_estates.php",
            "next_action": "Passer a la revue metier puis import ou hydratation KPI.",
            "caveat": "Annuaire volontaire : absence du fichier ne prouve pas absence de certification."
        },
        {
            "source_key": "bnsc_bike_parking",
            "priority": 4,
            "label": "BNSC stationnement cyclable",
            "status": "missing_output",
            "row_count": 0,
            "output_file": "sources/bnsc-bike-parking-normalized.csv",
            "schema_file": "sources/bnsc-bike-parking.schema.csv",
            "missing_columns": [],
            "gates": {
                "schema_exists": true,
                "output_exists": false,
                "has_rows": false,
                "headers_match_schema": false,
                "has_source_key": false,
                "has_caveat": false
            },
            "command": "php scripts/normalize_bnsc_bike_parking.php",
            "next_action": "Executer la normalisation pour produire le CSV cible.",
            "caveat": "Source OSM contributive : ne pas presenter comme label Accueil Velo ni frequentation."
        },
        {
            "source_key": "agencebio_organic_wine",
            "priority": 4,
            "label": "Agence Bio operateurs bio vin",
            "status": "qa_ready",
            "row_count": 3619,
            "output_file": "sources/agencebio-organic-wine-operators-normalized.csv",
            "schema_file": "sources/agencebio-organic-wine.schema.csv",
            "missing_columns": [],
            "gates": {
                "schema_exists": true,
                "output_exists": true,
                "has_rows": true,
                "headers_match_schema": true,
                "has_source_key": true,
                "has_caveat": true
            },
            "command": "php scripts/normalize_agencebio_organic_wine.php",
            "next_action": "Passer a la revue metier puis import ou hydratation KPI.",
            "caveat": "Annuaire declaratif valide par certificateurs ; groupe culture VI requis pour les surfaces bio viticoles."
        },
        {
            "source_key": "agencebio_organic_viticulture_surfaces",
            "priority": 5,
            "label": "Agence Bio surfaces viticoles bio communales",
            "status": "missing_publication_columns",
            "row_count": 53408,
            "output_file": "sources/agencebio-organic-viticulture-surfaces-normalized.csv",
            "schema_file": "sources/agencebio-organic-viticulture-surfaces.schema.csv",
            "missing_columns": [],
            "gates": {
                "schema_exists": true,
                "output_exists": true,
                "has_rows": true,
                "headers_match_schema": true,
                "has_source_key": true,
                "has_caveat": false
            },
            "command": "php scripts/normalize_agencebio_organic_viticulture_surfaces.php",
            "next_action": "Ajouter source_key et caveat avant import/publication.",
            "caveat": "VI correspond a la viticulture et inclut une faible part de raisin de table."
        },
        {
            "source_key": "franceagrimer_bulk_prices",
            "priority": 6,
            "label": "FranceAgriMer prix vrac",
            "status": "missing_output",
            "row_count": 0,
            "output_file": "sources/franceagrimer-prices.csv",
            "schema_file": "sources/franceagrimer-prices.schema.csv",
            "missing_columns": [
                "source_key",
                "source_row_number",
                "campaign",
                "period_date",
                "week",
                "wine_category",
                "colour",
                "segment",
                "geography",
                "price_value",
                "unit",
                "volume_hl",
                "source_label",
                "normalization_status",
                "publication_scope",
                "caveat"
            ],
            "gates": {
                "schema_exists": true,
                "output_exists": false,
                "has_rows": false,
                "headers_match_schema": false,
                "has_source_key": false,
                "has_caveat": false
            },
            "command": "php scripts/normalize_franceagrimer_bulk_prices.php",
            "next_action": "Executer la normalisation pour produire le CSV cible.",
            "caveat": "Prix France/segment large, pas prix appellation/local par defaut."
        },
        {
            "source_key": "dgddi_vitivinicole_stocks_harvests",
            "priority": 7,
            "label": "DGDDI recoltes et stocks",
            "status": "missing_output",
            "row_count": 0,
            "output_file": "sources/dgddi-vitivinicole-stocks-harvests.csv",
            "schema_file": "sources/dgddi-vitivinicole-stocks-harvests.schema.csv",
            "missing_columns": [
                "source_key",
                "source_row_number",
                "type",
                "year",
                "campaign",
                "department",
                "department_label",
                "category",
                "colour",
                "appellation_or_sign",
                "surface_ha",
                "production_hl",
                "stock_hl",
                "declarations",
                "unit",
                "source_resource",
                "normalization_status",
                "publication_scope",
                "caveat"
            ],
            "gates": {
                "schema_exists": true,
                "output_exists": false,
                "has_rows": false,
                "headers_match_schema": false,
                "has_source_key": false,
                "has_caveat": false
            },
            "command": "php scripts/normalize_dgddi_vitivinicole_supply.php",
            "next_action": "Executer la normalisation pour produire le CSV cible.",
            "caveat": "Jeu historique : ne pas publier comme conjoncture recente sans controle."
        },
        {
            "source_key": "agreste_vineyard_land_values",
            "priority": 8,
            "label": "Agreste valeur venale vignes",
            "status": "missing_output",
            "row_count": 0,
            "output_file": "sources/agreste-vineyard-land-values.csv",
            "schema_file": "sources/agreste-vineyard-land-values.schema.csv",
            "missing_columns": [
                "source_key",
                "source_row_number",
                "year",
                "territory_level",
                "territory_code",
                "territory_label",
                "region",
                "department",
                "pra",
                "vineyard_type",
                "price_mean_eur_ha",
                "price_min_eur_ha",
                "price_max_eur_ha",
                "evolution_rate",
                "unit",
                "source_label",
                "normalization_status",
                "publication_scope",
                "caveat"
            ],
            "gates": {
                "schema_exists": true,
                "output_exists": false,
                "has_rows": false,
                "headers_match_schema": false,
                "has_source_key": false,
                "has_caveat": false
            },
            "command": "php scripts/normalize_agreste_vineyard_land_values.php",
            "next_action": "Executer la normalisation pour produire le CSV cible.",
            "caveat": "Valeurs SAFER lissees : pas transaction brute ni expertise fonciere."
        }
    ],
    "copy_markdown": "# Reference Normalization Quality Gates\n\nQuality gates pour CSV normalises Winerix : schema, output, lignes, en-tetes, source_key et caveat avant import ou publication.\n\n## Synthese\n- Sources controlees : 11\n- QA ready : 3\n- Bloquees : 8\n- Prochaine source QA ready : qualite_tourisme_establishments\n- Premier blocage : sirene_wine_establishments\n\n## Gates par source\n\n### P1 - Sirene etablissements vin\n- Statut : `missing_output`\n- Lignes : 0\n- Output : `sources/sirene-wine-establishments-normalized.csv`\n- Schema : `sources/sirene-wine-establishments-normalized.schema.csv`\n- Colonnes manquantes : source_key, source_row_number, siren, siret, nic, establishment_name, naf_code, naf_label, wine_activity_family, is_active, is_headquarters, creation_date, last_treatment_date, address_raw, postcode, commune, commune_code, department, region, normalized_join_key, publication_scope, caveat\n- Prochaine action : Executer la normalisation pour produire le CSV cible.\n- Caveat : Donnees nominatives : RGPD/metier avant listing public.\n\n### P2 - BAN qualite adresse\n- Statut : `missing_output`\n- Lignes : 0\n- Output : `sources/ban-address-quality.csv`\n- Schema : `sources/ban-address-quality.schema.csv`\n- Colonnes manquantes : source_key, source_row_number, entity_type, entity_id, entity_name, address_raw, postcode, commune, citycode, ban_label, lon, lat, score, address_score, certified, geocoding_status, address_fingerprint, caveat\n- Prochaine action : Executer la normalisation pour produire le CSV cible.\n- Caveat : Adresse geocodee ne prouve pas ouverture au public ni frequentation.\n\n### P3 - Insee frequentation hebergements touristiques\n- Statut : `missing_output`\n- Lignes : 0\n- Output : `sources/insee-tourism-occupancy-normalized.csv`\n- Schema : `sources/insee-tourism-occupancy.schema.csv`\n- Colonnes manquantes : aucune\n- Prochaine action : Executer la normalisation pour produire le CSV cible.\n- Caveat : Demande hebergements generale, pas attribution oenotouristique directe.\n\n### P3 - Qualite Tourisme etablissements\n- Statut : `qa_ready`\n- Lignes : 448\n- Output : `sources/qualite-tourisme-establishments-normalized.csv`\n- Schema : `sources/qualite-tourisme-establishments.schema.csv`\n- Colonnes manquantes : aucune\n- Prochaine action : Passer a la revue metier puis import ou hydratation KPI.\n- Caveat : Label accueil/prestations, pas frequentation ni preuve oenotouristique directe.\n\n### P3 - Exploitations certifiees HVE\n- Statut : `qa_ready`\n- Lignes : 25329\n- Output : `sources/hve-certified-estates-normalized.csv`\n- Schema : `sources/hve-certified-estates-normalized.schema.csv`\n- Colonnes manquantes : aucune\n- Prochaine action : Passer a la revue metier puis import ou hydratation KPI.\n- Caveat : Annuaire volontaire : absence du fichier ne prouve pas absence de certification.\n\n### P4 - BNSC stationnement cyclable\n- Statut : `missing_output`\n- Lignes : 0\n- Output : `sources/bnsc-bike-parking-normalized.csv`\n- Schema : `sources/bnsc-bike-parking.schema.csv`\n- Colonnes manquantes : aucune\n- Prochaine action : Executer la normalisation pour produire le CSV cible.\n- Caveat : Source OSM contributive : ne pas presenter comme label Accueil Velo ni frequentation.\n\n### P4 - Agence Bio operateurs bio vin\n- Statut : `qa_ready`\n- Lignes : 3619\n- Output : `sources/agencebio-organic-wine-operators-normalized.csv`\n- Schema : `sources/agencebio-organic-wine.schema.csv`\n- Colonnes manquantes : aucune\n- Prochaine action : Passer a la revue metier puis import ou hydratation KPI.\n- Caveat : Annuaire declaratif valide par certificateurs ; groupe culture VI requis pour les surfaces bio viticoles.\n\n### P5 - Agence Bio surfaces viticoles bio communales\n- Statut : `missing_publication_columns`\n- Lignes : 53408\n- Output : `sources/agencebio-organic-viticulture-surfaces-normalized.csv`\n- Schema : `sources/agencebio-organic-viticulture-surfaces.schema.csv`\n- Colonnes manquantes : aucune\n- Prochaine action : Ajouter source_key et caveat avant import/publication.\n- Caveat : VI correspond a la viticulture et inclut une faible part de raisin de table.\n\n### P6 - FranceAgriMer prix vrac\n- Statut : `missing_output`\n- Lignes : 0\n- Output : `sources/franceagrimer-prices.csv`\n- Schema : `sources/franceagrimer-prices.schema.csv`\n- Colonnes manquantes : source_key, source_row_number, campaign, period_date, week, wine_category, colour, segment, geography, price_value, unit, volume_hl, source_label, normalization_status, publication_scope, caveat\n- Prochaine action : Executer la normalisation pour produire le CSV cible.\n- Caveat : Prix France/segment large, pas prix appellation/local par defaut.\n\n### P7 - DGDDI recoltes et stocks\n- Statut : `missing_output`\n- Lignes : 0\n- Output : `sources/dgddi-vitivinicole-stocks-harvests.csv`\n- Schema : `sources/dgddi-vitivinicole-stocks-harvests.schema.csv`\n- Colonnes manquantes : source_key, source_row_number, type, year, campaign, department, department_label, category, colour, appellation_or_sign, surface_ha, production_hl, stock_hl, declarations, unit, source_resource, normalization_status, publication_scope, caveat\n- Prochaine action : Executer la normalisation pour produire le CSV cible.\n- Caveat : Jeu historique : ne pas publier comme conjoncture recente sans controle.\n\n### P8 - Agreste valeur venale vignes\n- Statut : `missing_output`\n- Lignes : 0\n- Output : `sources/agreste-vineyard-land-values.csv`\n- Schema : `sources/agreste-vineyard-land-values.schema.csv`\n- Colonnes manquantes : source_key, source_row_number, year, territory_level, territory_code, territory_label, region, department, pra, vineyard_type, price_mean_eur_ha, price_min_eur_ha, price_max_eur_ha, evolution_rate, unit, source_label, normalization_status, publication_scope, caveat\n- Prochaine action : Executer la normalisation pour produire le CSV cible.\n- Caveat : Valeurs SAFER lissees : pas transaction brute ni expertise fonciere.\n"
}