diff --git a/.paul/STATE.md b/.paul/STATE.md
index 80479de..810b7c5 100644
--- a/.paul/STATE.md
+++ b/.paul/STATE.md
@@ -2,15 +2,15 @@
## Current Position
-Milestone: (ad-hoc) Supplemental feed — custom_label_1
-Phase: 2 of 2 (Supplemental Feed CL1) — Completed
-Plan: 02-01 unified (loop closed)
+Milestone: (ad-hoc) Products — widok "wszystkie kampanie"
+Phase: 3 of 3 (Products All Campaigns View) — Completed
+Plan: 03-01 unified (loop closed)
Status: UNIFY complete
-Last activity: 2026-04-22 — Zamknięto pętlę planu 02-01
+Last activity: 2026-04-24 — Zamknięto pętlę planu 03-01
Progress:
- Milestone: [██████████] 100%
-- Phase 2: [██████████] 100%
+- Phase 3: [██████████] 100%
## Loop Position
@@ -21,10 +21,10 @@ PLAN ──▶ APPLY ──▶ UNIFY
## Session Continuity
-Last session: 2026-04-22
+Last session: 2026-04-24
Stopped at: Loop closed, pętla gotowa do nowego /paul:plan
-Next action: Deploy na produkcję już wykonany; w razie kolejnego zadania — `/paul:plan` z opisem
-Resume file: .paul/phases/02-supplemental-feed-cl1/02-01-SUMMARY.md
+Next action: Wdróż `templates/products/main_view.php` na produkcję (FTP sync); w razie kolejnego zadania — `/paul:plan` z opisem
+Resume file: .paul/phases/03-products-all-campaigns-view/03-01-SUMMARY.md
## Historia zrealizowanych planów
@@ -36,9 +36,21 @@ Resume file: .paul/phases/02-supplemental-feed-cl1/02-01-SUMMARY.md
- 1 plik zmodyfikowany: autoload/services/class.SupplementalFeed.php (+6/-4)
- 4 AC spełnione
- 0 odchyleń — plan 1:1
+- `03-01-PLAN.md` — Powrót do widoku "wszystkie kampanie" w /products (completed 2026-04-24)
+ - 1 plik zmodyfikowany: templates/products/main_view.php (+1/-3)
+ - Zmiana: usunięto `placeholder: '- wybierz -'` i `allowClear: true` z Select2 dla `#products_campaign_id` / `#products_ad_group_id`
+ - 4 AC spełnione
+ - 1 kosmetyczna różnica w verify (allowClear na linii 2097 to niezwiązany Google taxonomy picker, poza zakresem)
+
+## Decisions
+
+| Date | Decision | Phase | Impact |
+|------|----------|-------|--------|
+| 2026-04-24 | Usunięcie placeholdera zamiast wprowadzania wartości sentinel `0`/`all` — minimalny blast radius | 3 | 1-linijkowa zmiana w JS, brak zmian w kontrolerze/factory |
## Notes
- PAUL framework działa w trybie ad-hoc (bez pełnej roadmapy/PROJECT.md).
-- Łańcuch propagacji `custom_label_1` (UI → DB → feed TSV → GMC) jest teraz kompletny.
-- Następne zmiany: uruchom `/paul:plan` z opisem kolejnego zadania.
+- Backend `factory\Products::build_scope_filters` już dziś traktuje `campaign_id ≤ 0` jako "bez filtra" — fix był wyłącznie po stronie JS.
+- Ustalony wzorzec: **Select2 + `` ⇒ NIE konfigurować `placeholder` ani `allowClear`**, żeby opcja pozostała widoczna w dropdownie po selekcji.
+- Deploy: wymaga FTP sync szablonu + hard reload (Ctrl+Shift+R) w przeglądarce klientów.
diff --git a/.paul/changelog/2026-04-24.md b/.paul/changelog/2026-04-24.md
new file mode 100644
index 0000000..65809f3
--- /dev/null
+++ b/.paul/changelog/2026-04-24.md
@@ -0,0 +1,12 @@
+# 2026-04-24
+
+## Co zrobiono
+
+- [Phase 3, Plan 01] Przywrócono widok "wszystkie kampanie" w filtrze na `/products`
+- Usunięto `placeholder: '- wybierz -'` oraz `allowClear: true` z konfiguracji Select2 w `init_products_scope_select_search()` — opcja `` (oraz analogiczna dla grup reklam) znów jest widoczna w dropdownie po dowolnej selekcji
+- Zweryfikowano 4 AC manualnie w przeglądarce (powrót do agregatu dla kampanii, dla grup reklam, persist po F5, brak regresji filtrów/sortowania/edycji)
+- Żadnych zmian w backendzie — `factory\Products::build_scope_filters` już dziś obsługuje `campaign_id ≤ 0` jako "bez filtra"
+
+## Zmienione pliki
+
+- `templates/products/main_view.php`
diff --git a/.paul/governance/governance_2026-04-24.jsonl b/.paul/governance/governance_2026-04-24.jsonl
new file mode 100644
index 0000000..6aceb4d
--- /dev/null
+++ b/.paul/governance/governance_2026-04-24.jsonl
@@ -0,0 +1,8 @@
+{"ts":"2026-04-24T20:59:59Z","tool":"Bash","cmd":"mkdir -p \".paul/phases/03-products-all-campaigns-view\"\",\"description\":\"Create phase directory\"},\"tool_response\":{\"stdout\":\"\",\"stderr\":\"\",\"interrupted\":false,\"isImage\":false,\"noOu","cwd":"/c/visual studio code/projekty/adsPRO"}
+{"ts":"2026-04-24T21:01:21Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\adsPRO\\\\.paul\\\\phases\\\\03-products-all-campaigns-view\\\\03-01-PLAN.md","cwd":"/c/visual studio code/projekty/adsPRO"}
+{"ts":"2026-04-24T21:01:39Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\adsPRO\\\\.paul\\\\STATE.md","cwd":"/c/visual studio code/projekty/adsPRO"}
+{"ts":"2026-04-24T21:02:27Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\adsPRO\\\\templates\\\\products\\\\main_view.php","cwd":"/c/visual studio code/projekty/adsPRO"}
+{"ts":"2026-04-24T21:03:50Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\adsPRO\\\\.paul\\\\STATE.md","cwd":"/c/visual studio code/projekty/adsPRO"}
+{"ts":"2026-04-24T21:05:08Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\adsPRO\\\\.paul\\\\phases\\\\03-products-all-campaigns-view\\\\03-01-SUMMARY.md","cwd":"/c/visual studio code/projekty/adsPRO"}
+{"ts":"2026-04-24T21:05:21Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\adsPRO\\\\.paul\\\\changelog\\\\2026-04-24.md","cwd":"/c/visual studio code/projekty/adsPRO"}
+{"ts":"2026-04-24T21:05:43Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\adsPRO\\\\.paul\\\\STATE.md","cwd":"/c/visual studio code/projekty/adsPRO"}
diff --git a/.paul/phases/03-products-all-campaigns-view/03-01-PLAN.md b/.paul/phases/03-products-all-campaigns-view/03-01-PLAN.md
new file mode 100644
index 0000000..a5e6505
--- /dev/null
+++ b/.paul/phases/03-products-all-campaigns-view/03-01-PLAN.md
@@ -0,0 +1,183 @@
+---
+phase: 03-products-all-campaigns-view
+plan: 01
+type: execute
+wave: 1
+depends_on: []
+files_modified:
+ - templates/products/main_view.php
+autonomous: false
+delegation: off
+---
+
+
+## Goal
+Przywrócić na stronie `/products` możliwość wyboru widoku "wszystkie kampanie" (agregacji) po wcześniejszym wybraniu konkretnej kampanii w filtrze `#products_campaign_id`. Analogicznie dla filtru grup reklam `#products_ad_group_id`.
+
+## Purpose
+Obecnie po wybraniu dowolnej kampanii użytkownik nie widzi już opcji "- wszystkie kampanie -" w rozwijanej liście i nie może wrócić do widoku zbiorczego (ani zrestartować filtra grupy reklam). Jedynym sposobem jest zmiana klienta albo ręczne wyczyszczenie `localStorage`. To psuje podstawowy przepływ pracy na liście produktów.
+
+## Output
+Zmodyfikowany plik `templates/products/main_view.php` — zmiana konfiguracji Select2 w `init_products_scope_select_search()` tak, aby opcja z pustą wartością ("- wszystkie kampanie -" / "- wszystkie grupy -") była stale widoczna w rozwijanej liście i dała się kliknąć w dowolnym momencie.
+
+
+
+## Project Context
+@.paul/STATE.md
+@CLAUDE.md
+
+## Source Files
+@templates/products/main_view.php
+@autoload/controls/class.Products.php
+@autoload/factory/class.Products.php
+
+## Prior Work
+Nie wymaga wczytywania poprzednich SUMMARY — ten plan nie jest zależny od milestone'a CL1. Dotyczy innej warstwy (UI filtra) tej samej strony `/products`, co plany 01-01 i 02-01.
+
+## Kluczowe fakty z analizy
+- Szablon `templates/products/main_view.php` już zawiera `` (linia ~19) oraz `` (linia ~27).
+- `init_products_scope_select_search()` (linia ~510) inicjuje Select2 z `placeholder: '- wybierz -'` i `allowClear: true`. Zgodnie z zachowaniem Select2, opcja z pustą wartością jest traktowana jako placeholder i ukrywana z dropdownu, co uniemożliwia jej ponowne wybranie po zmianie selekcji.
+- Backend (`factory\Products::build_scope_filters`, linia 470) filtruje po kampanii / grupie reklam TYLKO gdy `campaign_id > 0` / `ad_group_id > 0`. Pusty `campaign_id` już teraz daje widok zbiorczy — zmiana wyłącznie po stronie JS.
+- AJAX DataTable (`/products/get_products/`, linia ~537) wysyła `d.campaign_id = $('#products_campaign_id').val() || ''` — pusty string trafia do kontrolera, `(int)''` = 0, więc zagregowany widok działa bez zmian w kontrolerze.
+- Pozostałe funkcje (`load_scope_alerts`, `load_zero_impressions_products`, `update_delete_ad_group_button_state`) poprawnie krótko-spięte dla pustego `campaign_id` — wyłączają swoje panele, co jest pożądanym zachowaniem w widoku zbiorczym.
+
+
+
+
+## AC-1: Powrót do widoku "wszystkie kampanie" po wyborze kampanii
+```gherkin
+Given użytkownik jest na /products i wybrał klienta z co najmniej jedną kampanią
+ And wybrał konkretną kampanię w filtrze "Kampania"
+ And tabela produktów pokazuje wyniki przefiltrowane do tej kampanii
+When użytkownik rozwija dropdown "Kampania"
+Then w liście wyboru widzi pozycję "- wszystkie kampanie -"
+ And po jej kliknięciu wartość `#products_campaign_id` staje się pusta
+ And tabela `#products` przeładowuje się i pokazuje produkty ze wszystkich kampanii klienta (zagregowane po `products_aggregate` dla całego `client_id`)
+ And panele boczne "Produkty do sprawdzenia" oraz alerty zakresu (scope alerts) są ukryte (bo wymagają konkretnej kampanii)
+```
+
+## AC-2: Powrót do widoku "wszystkie grupy" po wyborze grupy reklam
+```gherkin
+Given użytkownik ma wybraną kampanię oraz konkretną grupę reklam w filtrze "Grupa reklam"
+When użytkownik rozwija dropdown "Grupa reklam"
+Then w liście wyboru widzi pozycję "- wszystkie grupy -"
+ And po jej kliknięciu wartość `#products_ad_group_id` staje się pusta
+ And tabela `#products` przeładowuje się i pokazuje produkty ze wszystkich grup reklam wybranej kampanii
+ And przycisk "Usuń grupę reklam" (`#delete-products-ad-group`) jest nieaktywny
+```
+
+## AC-3: Stan zachowany w localStorage po odświeżeniu strony
+```gherkin
+Given użytkownik wrócił do "wszystkich kampanii" (pusty `#products_campaign_id`)
+When odświeży stronę (`F5`)
+Then filtr "Kampania" pokazuje "- wszystkie kampanie -" jako aktualną wartość
+ And filtr "Grupa reklam" pokazuje "- wszystkie grupy -"
+ And tabela `#products` od razu ładuje zagregowany widok bez błędów konsoli
+```
+
+## AC-4: Brak regresji dla istniejących ścieżek
+```gherkin
+Given strona /products po zmianie
+When użytkownik wybierze klienta → kampanię → grupę reklam → produkt
+Then wszystkie istniejące przepływy działają jak dotychczas:
+ - filtry tekstowe (search, CL1, CL4) aktualizują tabelę
+ - sortowanie kolumn, paginacja DataTables działają
+ - edycja `custom_label_1` / `custom_label_4`, `min_roas` zapisuje się
+ - "Usuń grupę reklam" działa wyłącznie dla kampanii SHOPPING z wybraną grupą
+ - brak regresji w alertach zakresu i panelu "Produkty do sprawdzenia"
+```
+
+
+
+
+
+
+ Task 1: Naprawa konfiguracji Select2 w init_products_scope_select_search()
+ templates/products/main_view.php
+
+ W funkcji `init_products_scope_select_search()` (około linii 510–527) zmień konfigurację Select2 dla selektorów `#products_campaign_id` i `#products_ad_group_id`, aby opcja z pustą wartością była dostępna do wyboru w dropdownie.
+
+ Zmiana:
+ - Usuń parametry `placeholder: '- wybierz -'` oraz `allowClear: true`. Select2 bez `placeholder` nie promuje pierwszej pustej opcji do roli placeholdera — dzięki czemu `` (i odpowiednio "- wszystkie grupy -") pozostaje normalną pozycją listy, klikalną po selekcji innej opcji.
+ - Pozostaw `width: '100%'` oraz `data( 'products-select2-ready', true )` bez zmian.
+ - Nie dodawaj `minimumResultsForSearch` — domyślna wyszukiwarka wewnątrz dropdownu dalej jest pożądana przy większej liczbie kampanii.
+
+ Dlaczego dokładnie tak:
+ - Dokumentacja Select2: "If you do not specify a placeholder, a clear option will not be shown" — usunięcie placeholdera jest jednym krokiem, który przywraca widoczność pustej opcji i zarazem neutralizuje wymóg `allowClear`.
+ - Nie trzeba zmieniać wartości `')` przy każdym przeładowaniu.
+
+
+ 1. Otwórz plik `templates/products/main_view.php`, znajdź funkcję `init_products_scope_select_search` — potwierdź, że blok `$select.select2({...})` zawiera tylko `width: '100%'`.
+ 2. `php -l "templates/products/main_view.php"` → "No syntax errors detected".
+ 3. Szybki `grep -n "placeholder: '- wybierz -'" templates/products/main_view.php` → brak wyników.
+ 4. Szybki `grep -n "allowClear" templates/products/main_view.php` → brak wyników.
+
+ AC-1, AC-2 i AC-4 satysfakcjonowalne: opcja "wszystkie kampanie/grupy" widoczna w dropdownie po każdej selekcji; reszta przepływu bez regresji.
+
+
+
+
+ Naprawa filtra kampanii i grup reklam na stronie /products: przywrócenie widoczności opcji "- wszystkie kampanie -" oraz "- wszystkie grupy -" w rozwijanej liście Select2 po wcześniejszej selekcji konkretnej wartości.
+
+
+ 1. Wdróż zmianę na `https://adspro.projectpro.pl` (lub lokalne środowisko z tą bazą).
+ 2. Otwórz `https://adspro.projectpro.pl/products` (Hard Reload: Ctrl+Shift+R, aby odświeżyć cache JS).
+ 3. Wybierz klienta, który ma co najmniej 2 kampanie Shopping/PMax z produktami.
+ 4. AC-1: Rozwiń filtr "Kampania", wybierz konkretną kampanię → tabela pokazuje produkty tej kampanii. Rozwiń filtr ponownie → pierwsza pozycja listy to "- wszystkie kampanie -". Kliknij ją → tabela przeładowuje się i pokazuje zagregowane produkty wszystkich kampanii klienta; panele "Produkty do sprawdzenia" i alerty są ukryte.
+ 5. AC-2: Wybierz kampanię → wybierz konkretną grupę reklam → tabela ją filtruje. Rozwiń filtr "Grupa reklam" → pozycja "- wszystkie grupy -" jest widoczna i klikalna; po wybraniu tabela wraca do widoku wszystkich grup kampanii, a przycisk "Usuń grupę reklam" jest wyszarzony.
+ 6. AC-3: Ustaw filtr w trybie "wszystkie kampanie" → wykonaj F5. Po reloadzie dropdowny pokazują "- wszystkie kampanie -" / "- wszystkie grupy -" i tabela ładuje zagregowany widok bez błędów w konsoli (F12 → Console).
+ 7. AC-4 (regresje):
+ - Wyszukiwarka (`#products_search`) + filtry CL1/CL4 działają w widoku "wszystkich kampanii" oraz w widoku konkretnej kampanii.
+ - Sortowanie kolumn (np. ROAS, clicks_30) + paginacja DataTables nie wyrzucają błędów.
+ - Edycja inline `custom_label_1`, `custom_label_4` i `min_roas` poprawnie zapisuje wartości.
+ - "Usuń grupę reklam" działa dla kampanii SHOPPING z wybraną grupą.
+ 8. Sprawdź konsolę przeglądarki — nie powinno być błędów `Select2: The placeholder must be specified...` ani innych ostrzeżeń Select2.
+
+ Wpisz "approved" aby zamknąć plan, albo opisz problem do naprawienia (nowe odchylenie).
+
+
+
+
+
+
+## DO NOT CHANGE
+- `autoload/controls/class.Products.php` — kontroler już poprawnie obsługuje pusty `campaign_id` / `ad_group_id`.
+- `autoload/factory/class.Products.php` (w tym `build_scope_filters`, `get_products`, `get_records_total_products`, `get_roas_bounds`) — logika agregacji dla `client_id` bez filtrów kampanii jest sprawdzona i nie wymaga zmian.
+- HTML strony (sekcje `
+
+
+Przed uznaniem planu za zamknięty:
+- [ ] `php -l templates/products/main_view.php` → no syntax errors
+- [ ] `grep -n "placeholder: '- wybierz -'" templates/products/main_view.php` → brak trafień
+- [ ] `grep -n "allowClear" templates/products/main_view.php` → brak trafień
+- [ ] Brak błędów w konsoli przeglądarki na /products po zmianie
+- [ ] Checkpoint human-verify odhaczony (AC-1…AC-4 zweryfikowane ręcznie)
+
+
+
+- Użytkownik może z dowolnej selekcji w filtrze "Kampania" wrócić do widoku zbiorczego "- wszystkie kampanie -" jednym kliknięciem w dropdown.
+- To samo dla filtra "Grupa reklam".
+- Brak regresji w istniejących przepływach edycji, sortowania, usuwania grup reklam, AI suggestions, merchant sync i filtrów tekstowych.
+- Zmiana ograniczona do jednego pliku (`templates/products/main_view.php`), bez nowych zależności, bez migracji DB.
+
+
+
diff --git a/.paul/phases/03-products-all-campaigns-view/03-01-SUMMARY.md b/.paul/phases/03-products-all-campaigns-view/03-01-SUMMARY.md
new file mode 100644
index 0000000..9bc8cb5
--- /dev/null
+++ b/.paul/phases/03-products-all-campaigns-view/03-01-SUMMARY.md
@@ -0,0 +1,141 @@
+---
+phase: 03-products-all-campaigns-view
+plan: 01
+subsystem: ui
+tags: [select2, jquery, products, filter, frontend]
+
+requires:
+ - phase: (none)
+ provides: istniejący szablon /products oraz backend z `build_scope_filters` obsługującym już campaign_id ≤ 0
+
+provides:
+ - Widoczna opcja "- wszystkie kampanie -" w filtrze kampanii na /products po każdej selekcji
+ - Widoczna opcja "- wszystkie grupy -" w filtrze grup reklam na /products po każdej selekcji
+ - Przywrócony widok zagregowany bez konieczności czyszczenia localStorage / zmiany klienta
+
+affects:
+ - Każda przyszła zmiana w filtrach Select2 na /products (np. dodanie kolejnych filtrów ze scope)
+ - Ewentualne rozszerzenia filtrów analogicznych na innych stronach (sugerowane: /campaigns, jeśli używa podobnego wzorca Select2 z placeholderem + allowClear)
+
+tech-stack:
+ added: []
+ patterns:
+ - "Select2 z pustą opcją default: nie używać `placeholder` + `allowClear` jednocześnie, jeśli pierwsza