{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "09e5d9e7",
   "metadata": {},
   "source": [
    "# Moduł 10: Warsztat końcowy - diagnoza i rekomendacja Data Governance\n",
    "\n",
    "**Wersja:** uczestnika  \n",
    "**Cel:** połączyć profil danych, drift, oś czasu, target, artefakty dowodowe i odpowiedzialność w jedną rekomendację zarządczą  \n",
    "**Czas orientacyjny:** 60–75 min  \n",
    "**Dane:** customer360_prod.csv, customer360_reference.csv, feature_timing.csv, transformation_history.csv, model_report.csv  \n",
    "**Artefakt końcowy:** mini-raport decyzyjny do 2 stron A4 + załącznik techniczny z notebooka\n",
    "\n",
    "Notebook jest częścią wspólnego case'u **Customer 360**. Dane są syntetyczne i służą wyłącznie ćwiczeniu."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d75b5c14",
   "metadata": {},
   "source": [
    "## Jak pracować\n",
    "\n",
    "1. Uruchamiaj komórki od góry do dołu.\n",
    "2. Najpierw zapisz obserwację z danych. Dopiero później formułuj hipotezę o przyczynie.\n",
    "3. W rekomendacji wskaż dowód, właściciela działania i warunek ponownej oceny.\n",
    "4. Wynik statystyczny jest sygnałem diagnostycznym. Sam nie przesądza o zatrzymaniu modelu, zmianie progu ani retrainingu."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "325591a6",
   "metadata": {},
   "source": [
    "## Granice interpretacji\n",
    "\n",
    "- Wartości case, np. 15% -> 45%, są danymi scenariuszowymi, a nie benchmarkiem branżowym.\n",
    "- Wzrost odrzuceń jest obserwacją. Nie dowodzi sam w sobie driftu, awarii modelu ani problemu danych.\n",
    "- Encoded missing values, np. Unknown, pusty string i -99, mogą mieć różne znaczenie; nie mapuj ich automatycznie do zera.\n",
    "- Rozbieżność CRM/billing wymaga potwierdzenia wspólnej definicji i momentu snapshotu.\n",
    "- Raport rozdziela: obserwację, hipotezę, dowód, wpływ, rekomendację i właściciela."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4e80d50b",
   "metadata": {},
   "source": [
    "## Reguła operacyjna: od analizy do decyzji\n",
    "Notebook jest załącznikiem diagnostycznym. Nie maskuj problemu lokalnym czyszczeniem i nie przechodź bezpośrednio od alertu do retrainingu. Najpierw oddziel fakt, hipotezę i brakujący dowód. Dla krytycznego ryzyka dopuszczalny może być zatwierdzony fallback albo wstrzymanie automatyzacji, ale decyzja musi wynikać z wpływu, polityki procesu i przypisanej odpowiedzialności."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e422de61",
   "metadata": {},
   "source": [
    "## Dane wejściowe i manifest\n",
    "Dane: `customer360_prod.csv`, `customer360_reference.csv`, `feature_timing.csv`, `transformation_history.csv`, `model_report.csv`.  \n",
    "Opis kolumn i reguł laboratoryjnych: `manifests/M10_data_manifest.csv` w paczce zbiorczej albo `data_manifest.csv` w paczce modułowej."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bd361e1b",
   "metadata": {
    "tags": [
     "setup"
    ]
   },
   "outputs": [],
   "source": [
    "from pathlib import Path\n",
    "import sys\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "\n",
    "DATA_DIR = Path('data')\n",
    "if not DATA_DIR.exists():\n",
    "    DATA_DIR = Path('..') / 'data'\n",
    "assert DATA_DIR.exists(), 'Nie znaleziono katalogu data. Uruchom notebook z katalogu paczki lub zachowaj strukturę ZIP.'\n",
    "print('Python:', sys.version.split()[0])\n",
    "print('pandas:', pd.__version__)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "92486ce7",
   "metadata": {},
   "source": [
    "## 1. Profil danych produkcyjnych\n",
    "\n",
    "Znajdź jawne i zakodowane braki w income_raw, skrajny wiek, duplikaty oraz duże różnice sald. Dla sald przyjmij 1000 zł tylko jako próg diagnostyczny ćwiczenia."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a6c2e2c4",
   "metadata": {
    "tags": [
     "exercise"
    ]
   },
   "outputs": [],
   "source": [
    "prod=pd.read_csv(DATA_DIR/'customer360_prod.csv')\n",
    "# TODO: profil anomalii"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c64465a0",
   "metadata": {},
   "source": [
    "## 2. Drift i KS jako sygnały\n",
    "\n",
    "Porównaj age z reference przez KS oraz prosty PSI. Nie formułuj jeszcze rekomendacji retrainingu."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c3793275",
   "metadata": {
    "tags": [
     "exercise"
    ]
   },
   "outputs": [],
   "source": [
    "from scipy.stats import ks_2samp\n",
    "ref=pd.read_csv(DATA_DIR/'customer360_reference.csv')\n",
    "# TODO: KS i PSI"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ef593e2e",
   "metadata": {},
   "source": [
    "## 3. Oś czasu i potencjalne leakage\n",
    "\n",
    "Sprawdź feature_timing oraz rekordy, w których feature_available_time jest po prediction_time."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4ad5a16d",
   "metadata": {
    "tags": [
     "exercise"
    ]
   },
   "outputs": [],
   "source": [
    "timing=pd.read_csv(DATA_DIR/'feature_timing.csv')\n",
    "# TODO: potential_leakage i late_rows"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2924f5f4",
   "metadata": {},
   "source": [
    "## 4. Target i opóźnienie feedbacku\n",
    "\n",
    "Wczytaj raport modelowy. Sprawdź definicję targetu, okno obserwacji, opóźnienie raportowania oraz dojrzałość etykiet. Bieżącej metryki z niedojrzałymi etykietami nie traktuj jako ostatecznego dowodu degradacji ani concept driftu."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9976df55",
   "metadata": {
    "tags": [
     "exercise"
    ]
   },
   "outputs": [],
   "source": [
    "model_report=pd.read_csv(DATA_DIR/'model_report.csv')\n",
    "cols=['model','period_type','period','target_definition','target_window_days','reporting_delay_days','label_maturity_status','metric_status','roc_auc','decision_rate']\n",
    "display(model_report[cols])\n",
    "# TODO: wskaż bieżące wiersze, dla których etykiety nie są jeszcze dojrzałe"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "542e6288",
   "metadata": {},
   "source": [
    "## 5. Spójność materiału dowodowego\n",
    "\n",
    "Wczytaj historię transformacji i zestaw ją z raportem modelowym. Sprawdź, czy wersje i okresy pozwalają na analizę; luki oznacz jako luki, nie jako potwierdzoną przyczynę."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8178079f",
   "metadata": {
    "tags": [
     "exercise"
    ]
   },
   "outputs": [],
   "source": [
    "history=pd.read_csv(DATA_DIR/'transformation_history.csv')\n",
    "# model_report został wczytany w poprzednim kroku\n",
    "# TODO: evidence_table"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a65d6e27",
   "metadata": {},
   "source": [
    "## Szablon mini-raportu\n",
    "\n",
    "Po wykonaniu diagnozy przenieś wynik do `templates/M10_mini_raport_szablon.md`. Raport ma zmieścić się w maksymalnie 2 stronach A4 i zachować układ:\n",
    "\n",
    "**Streszczenie biznesowe → Diagnoza techniczna i dowody → RACI → Rekomendacje krótkoterminowe → Rekomendacje docelowe → Kryterium zamknięcia.**\n",
    "\n",
    "Notebook może zawierać więcej tabel i wykresów niż raport. Do raportu przenoś tylko informacje wspierające decyzję."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "090eaefd",
   "metadata": {},
   "source": [
    "## 6. Raport decyzyjny\n",
    "\n",
    "Zbuduj tabelę: **obserwacja → status fakt/hipoteza → dowód / brakujący dowód → wpływ → rekomendacja krótkoterminowa → rekomendacja docelowa → R → A → miernik zamknięcia**.\n",
    "\n",
    "W przypadku niedojrzałych etykiet zachowaj status `provisional`. Dla istotnego ryzyka możesz wskazać fallback lub zatrzymanie automatyzacji jako opcję krótkoterminową, ale tylko z warunkiem uruchomienia. Retraining nie jest reakcją domyślną."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "197efdd8",
   "metadata": {
    "tags": [
     "exercise"
    ]
   },
   "outputs": [],
   "source": [
    "final_report=pd.DataFrame(columns=[\n",
    "    'observation','status','evidence','missing_evidence','impact',\n",
    "    'short_term','target_state','R','A','closure_metric'\n",
    "])\n",
    "# TODO: uzupełnij co najmniej 5 wierszy. Każdy ma mieć R, jedną rolę A i miernik zamknięcia.\n",
    "display(final_report)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3d003f0d",
   "metadata": {},
   "source": [
    "## Zadanie rozszerzające\n",
    "\n",
    "Skróć `final_report` do pięciu zdań dla zarządu. Każde zdanie ma zachować status fakt/hipoteza, właściciela działania i warunek sprawdzenia efektu. Następnie przenieś treść do szablonu `M10_mini_raport_szablon.md`."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "01638ced",
   "metadata": {},
   "source": [
    "## Kryteria akceptacji ćwiczenia\n",
    "- oddzielasz fakt, hipotezę, brakujący dowód, wpływ i rekomendację\n",
    "- metryki z niedojrzałymi etykietami pozostają provisional\n",
    "- RACI ma wykonawcę R i jedną odpowiedzialność końcową A dla istotnego działania\n",
    "- raport ma rekomendacje krótkoterminowe i docelowe oraz mierzalny warunek zamknięcia\n",
    "\n",
    "Przed oddaniem wykonaj **Restart Kernel and Run All**. Notebook nie powinien zależeć od ręcznie ustawionego stanu poprzednich komórek."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "412ba4db",
   "metadata": {},
   "source": [
    "## Co oddajesz\n",
    "\n",
    "Zachowaj tabelę lub wykres będący wynikiem ćwiczenia oraz krótki komentarz: **obserwacja → hipoteza → potrzebny dowód → rekomendacja / dalszy krok**. Jeżeli nie da się rozstrzygnąć przyczyny na podstawie danych z notebooka, oznacz ją jako hipotezę i wskaż brakujący artefakt."
   ]
  }
 ],
 "metadata": {
  "course": {
   "generated": "2026-08-28",
   "module": 10,
   "variant": "participant"
  },
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python",
   "version": "3.x"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
