Pierwsza komenda do wywołania to aktywacja środowiska czyli : ..\infotracker-env\Scripts\activate.ps1
9 testów failuje (pre existing), ważne żeby nie failowało więcej.

## Wykonane (fakty)
- Aktywacja środowiska w PowerShell: ..\infotracker-env\Scripts\activate.ps1
- Przejrzany kod parsera/engine odpowiedzialny za zależności i OL inputs (parser.py, parser_modules/procedures.py, parser_modules/string_fallbacks.py, deps.py, engine.py, lineage.py).
- Debug na przykładzie StoredProcedure.dbo.update_FactSecInsurance_MSBRG.sql:
	- parse_sql_file zwraca obiekt `dbo.FactSecInsurance_MSBRG` z zależnościami:
		EDW_CORE.dbo.InsurancePolicy_MSBV, SnapshotControlTable_EligiblePoolCalendar_BV,
		Contract_MSPIT, InsuranceCompany_MSBV.
	- emit_ol_from_object generuje inputs z ww. tabel.
- Uruchomiono pytest -q: 9 testów FAIL (bez zmiany liczby faili).
- Sprawdzenie column_graph.json (build/output/full_prod_35):
	- FactSecInsurance_MSBRG ma w grafie krawędzie WYCHODZĄCE (jest rodzicem dla FactSecInsurance_MSBV),
		ale brak krawędzi WCHODZĄCYCH do samego FactSecInsurance_MSBRG.
	- Istnieją krawędzie do tymczasowego obiektu update_FactSecInsurance_MSBRG#InsurancePolicy_MSBV (temp).
- Sprawdzone artefakty OL:
	- StoredProcedure.dbo.update_FactSecInsurance_MSBRG.json ma inputs (4 tabele), ale brak facetu columnLineage.
	- Table.dbo.FactSecInsurance_MSBRG.json nie ma inputs ani columnLineage.
- Debug regexa INSERT...SELECT dla update_FactSecInsurance_MSBRG:
	- _extract_insert_select_lineage_string znajduje INSERT, ale parse SELECT pada na CASE i terminator regexa ucina zapytanie na słowie END,
		więc lineage/deps wychodzą puste.
- Ponowne pytest -q: 9 testów FAIL (bez zmiany liczby faili).
- Zmiana w logice: w regexie INSERT...SELECT usunięto END z listy terminatorów (żeby CASE ... END nie ucinało SELECT).
- Dodatkowa poprawka: obcięcie trailing "SELECT @..." w wycinku INSERT...SELECT (żeby nie psuć parsera).
- Weryfikacja po zmianach (lokalny build grafu dla update_FactSecInsurance_MSBRG):
	- obj_lineage_cols=8, in_edges=12 (wcześniej 0).
- pytest -q po zmianach: 9 testów FAIL (bez zmiany liczby faili).
- Wygenerowano nowy zestaw: build/output/full_prod_35_new (infotracker extract --sql-dir build/PROD).
- Porównanie column_graph (full_prod_35 vs full_prod_35_new) dla FactSecInsurance_MSBRG:
	- old_to=10 → new_to=21 (więcej krawędzi WCHODZĄCYCH), old_from=10 → new_from=10 (bez regresji).
- Sprawdzenie nowego artefaktu: StoredProcedure.dbo.update_FactSecInsurance_MSBRG.json ma columnLineage (8 pól).
- Sprawdzenie MSBRG w column_graph.json (build/output/full_prod_35_new):
	- 39 datasetów z „msbrg” w nazwie.
	- 4 bez krawędzi WCHODZĄCYCH (brak rodziców):
		- mssql://localhost/EDW_CORE.dbo.Annex8_MSBRG
		- mssql://localhost/EDW_CORE.dbo.Offer_MSbrg
		- mssql://localhost/EDW_CORE.dbo.tempFactSecCashMeasure_MSBRG
		- mssql://localhost/METRICS_CORE.dbo.EAAttribute_EAAttribute_MSBRG
- Wyszukiwanie procedur w build/PROD powiązanych z:
	- Annex8_MSBRG → StoredProcedure.dbo.update_OBT_Annex8_MSBRG.sql
	- Offer_MSbrg → StoredProcedure.dbo.update_Offer_BRG.sql (zawiera offer_msbrg)
- Analiza braku rodziców dla Annex8_MSBRG:
	- ColumnLineage brak w: StoredProcedure.dbo.update_OBT_Annex8_MSBRG.json i Table.dbo.Annex8_MSBRG.json (inputs=0 / lineage missing).
	- Porównanie column_graph: Annex8_MSBRG old=0 incoming, new=0 incoming (bez zmian po ostatnich poprawkach).
	- SQL procedury jest w UTF-16; po poprawnym odczycie regex znajduje INSERT INTO Annex8_MSBRG.
	- sqlglot parse SELECT w INSERT...SELECT wywraca się na kontrolnym znaku 0x1A w string literal (fReplacePolishCharacters(..., '␦', '')).
	  -> to blokuje columnLineage i przez to brak rodziców w grafie.
- pytest -q: 9 FAIL (bez zmiany liczby faili).
- Poprawki pod Annex8_MSBRG:
	- _normalize_tsql usuwa znak 0x1A.
	- regex INSERT...SELECT nie ucina na ';' wewnątrz string literal (zaostrzone warunki terminatora).
- Rebuild: build/output/full_prod_35_new2.
	- Table.dbo.Annex8_MSBRG.json ma columnLineage (110 pól).
	- Column_graph: Annex8_MSBRG incoming 0 → 92 (full_prod_35_new → full_prod_35_new2).
	- Suma krawędzi: 86741 → 86833 (brak regresji liczbowej).
- pytest -q po zmianach: 9 FAIL (bez zmiany liczby faili).
- Sprawdzenie Offer_MSbrg (full_prod_35_new2):
	- Table.dbo.Offer_MSBRG.json: columnLineage present (50 pól), inputs=59.
	- Column_graph incoming dla Offer_MSBRG: 50 (bez zmian vs full_prod_35_new).
- Fix temp FactEligibilityCriteria_TEMP:
	- W fallbacku stringowym rejestrowanie SELECT/INSERT INTO #temp do temp_registry/temp_sources (kanoniczna nazwa: dbo.update_FactSecEligibilityCrit#FactEligibilityCriteria_TEMP).
	- Rebuild: build/output/full_prod_35_new3.
	- column_graph (full_prod_35_new3):
		- dataset mssql://localhost/EDW_CORE.dbo.update_FactSecEligibilityCrit#FactEligibilityCriteria_TEMP ma incoming=55, outgoing=37.
		- dataset mssql://localhost/EDW_CORE.dbo.FactEligibilityCriteria_TEMP nie występuje w grafie (incoming/outgoing=0).
	- W grafie kolumnowym temp ma rodziców pod kanoniczną nazwą.
- pytest -q po zmianach: 10 FAIL (wzrost z 9 do 10; nowe regresje głównie w test_trialbalance_regression oraz test_cte_join_keywords/test_leadtime_regression).
- Start analizy tempów bez rodziców (full_prod_35_new3):
	- Pierwszy przypadek: dbo.update_ADUser_satst_ad_ADUser -> temp #RecordsToInsert (SELECT INTO z CTE NewHK/DisappearedHK).
	- SQL: #RecordsToInsert budowany z #StageSourceData (STG.dbo.stage_ad_ActiveDirectoryUserWithdrawn) i EDW_CORE.dbo.ActiveDirectoryUser_satst_ad_ADUserWithdrawn_current.
	- Parser: parse_sql_file sygnalizuje unsupported syntax CREATE PROCEDURE i fallbackuje do Command; temp_registry zawiera #RecordsToInsert, ale temp_sources i temp_lineage są puste.
	- Efekt: w column_graph temp #RecordsToInsert ma 0 incoming (brak rodziców).
- Zmiana: string_fallbacks._extract_materialized_output_from_procedure_string uzupełnia temp_sources/temp_lineage dla SELECT INTO #temp (best-effort lineage/deps z okna SELECT INTO).
- Dodatkowo: gdy deps z _extract_insert_select_lineage_string są puste, fallback bierze _extract_basic_dependencies i filtruje nazwy CTE (WITH ... AS) + tempdb.
- pytest -q po zmianach: 9 FAIL (test_cte_join_keywords już PASS; pozostałe to leadtime + trialbalance regressions).
- Temp #RecordsToInsert dla dbo.update_ActiveDirecto_22fadbaa:
	- SQL analogiczny do poprzedniego przypadku (SELECT INTO #StageSourceData + WITH NewHK/DisappearedHK -> SELECT INTO #RecordsToInsert).
	- Po aktualnych zmianach parser.temp_sources dla #RecordsToInsert zawiera: STG.dbo.stage_ActiveDirectoryUser_camino_user oraz EDW_CORE.dbo.ActiveDirectoryUser_satst_CAMINO_user_current.
	- Oczekiwany efekt w grafie po rebuildzie: temp #RecordsToInsert będzie miał rodziców.
- Odświeżono listę tempów bez rodziców na podstawie build/output/full_prod_40/column_graph.json:
	- build/output/full_prod_40/temp_tables_no_parents.txt (format: procedure | temp_dataset).
- pytest -q po odświeżeniu listy: 9 FAIL (bez zmiany liczby faili).
- Temp dbo.update_ADUser_satst_ad_ADUser#RecordsToInsert:
	- SELECT INTO #RecordsToInsert z CTE NewHK/DisappearedHK nie dawał temp_lineage (puste lineage mimo deps).
	- Dodano fallback: gdy brak lineage, ale są deps, wyciągany jest select-list z tego samego statementu i budowany jest podstawowy temp_lineage.
	- Weryfikacja przez SqlParser: temp_lineage dla #RecordsToInsert ma kolumny hk_h_ActiveDirectoryUser, DV_record_source, DV_load_date, DV_is_active z deps STG.dbo.stage_ad_ActiveDirectoryUserWithdrawn i EDW_CORE.dbo.ActiveDirectoryUser_satst_ad_ADUserWithdrawn_current.
- pytest -q po zmianach: 8 FAIL (spadek z 9; nadal leadtime + trialbalance regression).
- Odświeżono listę tempów bez rodziców dla full_prod_40 po zmianach:
	- build/output/full_prod_40/temp_tables_no_parents.txt.
	- update_ADUser_satst_ad_ADUser#RecordsToInsert nie występuje w nowej liście.
- Temp dbo.update_ActiveDirectoryUserGMU#TEMP_stage_mis_ActiveDirectoryGroupMemberUserHistory:
	- SELECT INTO temp dawał lineage bez inputów lub tylko do samego temp (brak rodziców w grafie).
	- Zmiana: gdy deps zawierają tylko temp lub lineage bez inputów, wymuszamy _extract_basic_dependencies i budujemy fallback lineage z listy SELECT.
	- Weryfikacja: temp_lineage mapuje kolumny na EDW_CORE.dbo.stage_mis_ActiveDirectoryGroupMemberUserHistory.
	- Rebuild full_prod_40 + refresh listy: temp nie występuje w build/output/full_prod_40/temp_tables_no_parents.txt.
	- pytest -q po zmianach: 8 FAIL (bez regresji vs poprzedni stan).
- Problem: pojawiały się nazwy kolumn z formułami (COALESCE/CASE/VARCHAR) po fallbacku stringowym.
	- Poprawa: split SELECT listy po przecinkach tylko na poziomie top-level i rozpoznanie aliasu tylko na top-level (bez CAST AS ...).
	- Dodatkowo: gdy SELECT list zawiera "kolumna typ" (np. nvarchar(max)), wybieramy nazwę kolumny zamiast typu.
	- Dla projekcji COALESCE bez aliasu używamy nazwy pierwszej kolumny zamiast "coalesce_expr".
	- Dodatkowo filtrujemy błędne nazwy w stylu "'nvarchar(max)')" i inne formułopodobne resztki.
	- Rebuild full_prod_40: skan column_graph.json nie wykazuje już kolumn z nazwami zawierającymi COALESCE/CASE/VARCHAR.
	- pytest -q po zmianach: 8 FAIL (bez regresji vs poprzedni stan).
- Temp edw_core.dbo.#stage_AssetGroupDictionary_sat_ms_mis_TEMP:
	- Źródłowy plik: build/PROD/EDW_CORE/StoredProcedures/StoredProcedure.dbo.update_AssetGroupDictionary_s.sql.
	- Temp jest tworzony przez SELECT INTO #stage_AssetGroupDictionary_sat_ms_mis_TEMP z EDW_CORE.dbo.stage_mis_ms_AssetGroupDictionary.
	- column_graph (full_prod_41) pokazuje krawędzie stage_mis_ms_AssetGroupDictionary -> #stage_AssetGroupDictionary_sat_ms_mis_TEMP, ale brak krawędzi do AssetGroupDictionary_sat_ms_mis.
	- W column_graph wystepuja tez wpisy z obcym prefiksem procedury (update_Person_sat_PII__8e7df6#stage_AssetGroupDictionary_sat_ms_mis_TEMP).
- pytest -q po aktualizacji notatek: 8 FAIL (bez zmiany liczby faili).
- Zmiana w parser_modules/procedures.py: gdy procedura materializuje tylko tempy, ale zawiera MERGE do tabeli trwałej, to preferujemy MERGE target jako output procedury (bez nadpisywania lineage przez insert-select fallback).
- Dodatkowa zmiana w _parse_procedure_body_statements: jesli fallback zwraca tylko temp (lub nic), a w SQL jest MERGE do tabeli trwałej, to promujemy MERGE target jako wynik procedury.
- pytest -q po zmianie w _parse_procedure_body_statements: 8 FAIL (bez zmiany liczby faili).
- Przyczyna bledu MERGE: regex OUTPUT ... INTO lapal OUTPUT z listy parametrow procedury i parowal z INTO z SELECT INTO, przez co target MERGE byl nadpisywany tempem.
- Poprawka: w _extract_merge_lineage_string parsujemy OUTPUT/USING/WHEN tylko w wycinku MERGE (merge_sql).
- Weryfikacja na StoredProcedure.dbo.update_AssetGroupDictionary_s.sql:
	- merge target: dbo.AssetGroupDictionary_sat_ms_mis.
	- parse_sql_file zwraca output: table dbo.AssetGroupDictionary_sat_ms_mis (zamiast temp).
- pytest -q po poprawce MERGE OUTPUT: 8 FAIL (bez zmiany liczby faili).

## Obserwacje
- „Brak rodziców” w viz wynika z braku columnLineage dla FactSecInsurance_MSBRG (graf kolumnowy opiera się na lineage, nie na dependencies).
- Zależności są w inputs procedury, ale nie przekładają się na column_graph (brak krawędzi bez lineage).
- Potencjalny problem może wynikać z tego, że w realnych MSBRG są wzorce SQL niepasujące do regexów
	(np. MERGE/EXEC/dynamic SQL/CTE poza oknem wyszukiwania), albo z braku artefaktów wyjściowych
	w folderze z OL (brak plików dla MSBRG).
- Dla temp #stage_AssetGroupDictionary_sat_ms_mis_TEMP column_graph wskazuje na bledne targetowanie MERGE (krawedzie trafiaja do temp zamiast do tabeli docelowej) i mozliwy problem z zakresowaniem temp (obcy prefiks procedury).

## Plan dalszych kroków (bez zmian w logice)
- Zweryfikować w podobnych MSBRG czy regex w _extract_insert_select_lineage_string ucina SELECT na END (CASE) i przez to brak lineage.
- Przygotować bezpieczną zmianę w regex terminatora (np. nie traktować END jako końca INSERT..SELECT) + testy.
- Zidentyfikować konkretne obiekty MSBRG bez rodziców w istniejących artefaktach OL (który folder, które pliki).
- Sprawdzić, czy dla tych obiektów są w ogóle generowane JSON-y w output (i czy to jest obiekt tabeli czy procedury).
- Uruchomić parser/emit na kilku problematycznych plikach i porównać dependencies vs. inputs w OL.
- Jeśli zależności są puste: sprawdzić wzorzec SQL (MERGE/EXEC/CTE/SELECT INTO) i dopasowanie regexów.
- Dla tempów: sprawdzić, czy SELECT INTO z CTE w procedurach przechodzi przez string fallback i czy powinno budować temp_sources/temp_lineage.
- Sprawdzic, czemu dla MERGE w update_AssetGroupDictionary_s column_graph generuje krawedzie do temp zamiast do AssetGroupDictionary_sat_ms_mis.
- Zweryfikowac zakresowanie temp w temp_registry/temp_sources (obcy prefiks procedury przy #stage_AssetGroupDictionary_sat_ms_mis_TEMP).

## Status problemu
- Problem „MSBRG bez rodziców” częściowo rozwiązany:
	- FactSecInsurance_MSBRG, Annex8_MSBRG, Offer_MSbrg oraz temp FactEligibilityCriteria_TEMP mają rodziców w column_graph.
	- Pozostałe przypadki wymagają identyfikacji i weryfikacji.