# Rozbudowa narzedzia

Ten plik opisuje, jak dodawac nowe grupy zadan, zadania i skrypty, zeby kolejny agent nie musial projektowac procesu od zera.

## Zasada architektury

Kazde zadanie powinno dzialac w tym samym modelu:

1. Pobierz aktualne dane.
2. Zbuduj plan.
3. Zapisz plan do `clients/<domena>/plans/` jako `.json` i `.md`.
4. W trybie `--plan-only` nie wdrazaj zmian.
5. Po akceptacji uzytkownika wdrazaj tylko plan zapisany w JSON.
6. Zapisz historie do:
   - `clients/<domena>/history/YYYY-MM-DD.jsonl`
   - `clients/<domena>/changes/YYYY-MM-DD.md`

Agent AI prowadzi uzytkownika, ale logika pobierania danych, analizy i wdrozenia zmian ma byc w Pythonie.

Wyjatek: zadanie `ai_account_audit` sluzy do strategicznego audytu rozmownego. Python pobiera i zapisuje pakiet danych, ale finalna diagnoza, pytania do uzytkownika i plan przyszlych dzialan sa przygotowywane przez agenta AI na podstawie JSON, Markdown i rozmowy. To zadanie nie wdraza zmian bezposrednio.

## Granice zadan i rytm kontroli

Jedno zadanie powinno miec jeden rytm kontroli i jeden typ decyzji. Nie mieszaj w jednym zadaniu prostych ustawien konfiguracyjnych, budzetow, strategii stawek, zapytan uzytkownikow i reklam, bo te obszary sprawdza sie z rozna czestotliwoscia i niosa inne ryzyka.

Przyklady podzialu:

- ustawienia podstawowe, np. lokalizacje, sieci, jezyki - zwykle raz w miesiacu albo po zmianach,
- budzety i pacing - zwykle co tydzien,
- strategie stawek - zwykle co tydzien albo co dwa tygodnie, z ocena wolumenu konwersji,
- zapytania i wykluczenia - zwykle co tydzien,
- reklamy i zasoby - zwykle co dwa do czterech tygodni,
- struktura konta i kampanii - zwykle miesiecznie albo kwartalnie.

Opis zadania w `config/tasks.toml` ma jasno mowic, co jest w zakresie i czego zadanie nie analizuje. Jesli obszar wymaga innej czestotliwosci, dodaj osobne zadanie albo osobna grupe.

## Dodanie nowej grupy zadan

Przed dodaniem wiekszego zakresu sprawdz:

```text
OLD_COMMANDS_CHECKLIST.md
```

To jest lista rzeczy sprawdzanych przez stary system z `D:\google ads\`.

Edytuj:

```text
config/tasks.toml
```

Dodaj nowa grupe:

```toml
[[groups]]
id = "search"
name = "Kampanie Search"
```

Zadania beda numerowane automatycznie jako `2.1`, `2.2`, itd. w zaleznosci od kolejnosci grup.

## Dodanie nowego zadania do grupy

W `config/tasks.toml` dodaj zadanie pod odpowiednia grupa:

```toml
[[groups.tasks]]
id = "check_search_settings"
name = "Sprawdzenie ustawien"
description = "Sprawdza ustawienia kampanii Search wedlug regul globalnych i wyjatkow klienta."
```

`id` jest techniczne i musi byc stabilne. `name` i `description` sa dla uzytkownika.

## Plik zadania w Pythonie

Dodaj modul w:

```text
src/gads_v2/tasks/
```

Przyklad nazwy:

```text
src/gads_v2/tasks/search_settings_check.py
```

Minimalny wzorzec funkcji:

```python
def run_check_search_settings(
    client_config: ClientConfig,
    global_rules: dict,
    plan_only: bool = False,
    apply_plan_path: str | None = None,
    confirm_apply: str | None = None,
    show_navigation: bool = True,
) -> None:
    ...
```

Wymagania:

- `plan_only=True` zawsze tylko zapisuje plan.
- `apply_plan_path` wdraza tylko wskazany plan JSON.
- `confirm_apply` musi wymagac wartosci `TAK`.
- `show_navigation=False` musi ukrywac pytanie `Co dalej`, bo uzywa tego tryb sekwencji.

## Struktura planu

Plan powinien miec klase lub slownik z metodami:

```python
to_dict()
from_dict()
```

Plan JSON musi zawierac:

```json
{
  "created_at": "...",
  "client": "example.pl",
  "task": "task_id",
  "changes": []
}
```

Plan Markdown powinien zawierac:

- krotkie podsumowanie,
- tabele po kampaniach, jesli zadanie dotyczy kampanii,
- tabele planowanych dzialan,
- ostrzezenia lub pominiete reguly.

## Podpiecie zadania do CLI

Edytuj:

```text
src/gads_v2/cli.py
```

1. Zaimportuj funkcje zadania:

```python
from .tasks.search_settings_check import run_check_search_settings
```

2. Dodaj `id` do argumentu `--task`:

```python
parser.add_argument("--task", choices=["sync_pla_cl1", "check_pla_settings", "check_search_settings"], ...)
```

3. Dodaj obsluge w `run_task()`:

```python
if task_id == "check_search_settings":
    run_check_search_settings(
        client,
        global_rules,
        plan_only=plan_only,
        apply_plan_path=apply_plan_path,
        confirm_apply=confirm_apply,
        show_navigation=show_navigation,
    )
    return
```

## Reguly globalne i wyjatki klientow

Reguly trzymaj w:

```text
config/clients.toml
```

Przyklad globalny:

```toml
[global_rules.search_settings]
require_presence_only = true
require_search_partners_off = true
```

Wyjatek per klient:

```toml
[clients."example.pl".search_settings]
require_search_partners_off = false
```

W kodzie uzywaj:

```python
rules = client_config.effective_rules(global_rules, "search_settings")
```

## Pominiecia zadan przy ALL

Jesli zadanie ma byc pomijane tylko przy pelnym wyborze `ALL` / `--all-groups`,
dodaj je przy konkretnym kliencie:

```toml
[clients."example.pl"]
google_ads_customer_id = "123-456-7890"
skip_in_all = ["split_pla_cl1_bestsellers"]
```

Pominiecie dotyczy tylko `ALL` / `--all-groups`. Reczny wybor zadania albo grupy
nadal uruchamia wskazany zakres.

## Numeracja i wybory

Lista zadan uzywa formatu:

```text
1.1 - pierwsze zadanie w pierwszej grupie
1.2 - drugie zadanie w pierwszej grupie
1.0 - wszystkie zadania z pierwszej grupy
ALL - wszystkie zadania ze wszystkich grup
```

Nie dodawaj recznej numeracji do `tasks.toml`. Numeracja wynika z kolejnosci grup i zadan.

## Test po dodaniu zadania

Uruchom:

```powershell
python -m compileall -q gads.py src
python gads.py analiza-klienta --client-number 1
python gads.py analiza-klienta --client-number 1 --select <nr> --plan-only
```

Jesli zadanie wdraza zmiany, przetestuj najpierw tylko `--plan-only`.

## Format komunikacji agentow

Instrukcja dla agentow jest w:

```text
AGENTS.md
```

Po dodaniu nowego typu zadania dopisz tam tylko specjalne zasady, jesli agent ma wiedziec cos ponad standardowy przeplyw.

## Rozbudowa bazy wiedzy

Baza wiedzy projektu jest w:

```text
knowledge/
```

Najwazniejsze pliki:

- `knowledge/sources/` - materialy zrodlowe, np. artykuly, notatki, eksport ze starej LanceDB.
- `knowledge/rules.jsonl` - atomowe reguly uzywane przez narzedzie.
- `knowledge/imports.jsonl` - historia importow.
- `knowledge/lancedb/` - metadane indeksu semantycznego. Fizyczny indeks LanceDB jest domyslnie w `%LOCALAPPDATA%\google-ads-ver2-knowledge-lancedb`, bo katalog projektu moze byc synchronizowany i blokowac operacje zapisu LanceDB.

Dodawanie wiedzy:

```powershell
python gads.py wiedza dodaj --file "knowledge/sources/plik.md" --source "czytelna_nazwa_zrodla" --dry-run
python gads.py wiedza dodaj --file "knowledge/sources/plik.md" --source "czytelna_nazwa_zrodla"
```

Jednorazowy import starej bazy LanceDB:

```powershell
python gads.py wiedza import-stare --from "D:\google ads\lancedb"
python gads.py wiedza indeksuj
```

Ten import nie przypisuje regul do zadan. `task_ids` oraz `suggested_task_ids` pozostaja puste.

Wznawialny przeglad regul bez przypisan:

```powershell
python gads.py wiedza przypisz
python gads.py wiedza przypisz --restart
```

Domyslnie `wiedza przypisz` pokazuje jedna regule, pelny kontekst decyzji i konczy porcje po jednej odpowiedzi. Reguly sa przegladane w kolejnosci zapisanej w `knowledge/rules.jsonl`, a nie sortowane po tematach. To ulatwia uzytkownikowi porownanie ekranu przegladu z plikiem i kolejnoscia importu. Wieksze partie uruchamiaj tylko jawnie, np. `python gads.py wiedza przypisz --limit 10`.

Zasady przegladu:

- `Q` przerywa bez przesuniecia kursora, wiec wznowienie zacznie od tej samej reguly.
- `P` pomija regule i zapisuje postep.
- `U` pyta o potwierdzenie `USUN`, a potem trwale usuwa biezaca regule z `knowledge/rules.jsonl`.
- Numer zadania lub `task_id` dopisuje regule do zadania.
- Po dodaniu nowych zadan do `config/tasks.toml` uruchom `python gads.py wiedza przypisz --restart`.
- Stan kursora jest w `knowledge/review_state.json`.
- Po usunieciu reguly stan kursora zapisuje takze klucz sortowania, zeby wznowienie zaczelo od nastepnej reguly mimo braku usunietego `id` w pliku.
- Po fizycznym usunieciu regul trzeba odbudowac LanceDB przez `python gads.py wiedza indeksuj`, bo indeks jest tylko lokalna kopia do wyszukiwania.

Zasady:

- Najpierw uruchom `--dry-run`, zeby sprawdzic plik bez kosztu API.
- Import przez API wymaga `OPENAI_API_KEY` w `.env`.
- Opcjonalny model ustaw przez `KNOWLEDGE_OPENAI_MODEL` albo `--model`.
- Reguly przypisuj tylko do istniejacych `task_id` z `config/tasks.toml`.
- Importer moze zapisac propozycje w `suggested_task_ids`, ale nie wolno uznawac ich za aktywne przypisanie do zadania.
- Regula staje sie regula zadania dopiero po akceptacji uzytkownika przez pytanie skryptu albo komenda:

```powershell
python gads.py wiedza zatwierdz --rule-id "<id_reguly>" --task "<task_id>"
```

- Odrzucenie propozycji:

```powershell
python gads.py wiedza odrzuc --rule-id "<id_reguly>" --task "<task_id>"
```

- Jesli wiedza dotyczy zadania, ktorego jeszcze nie ma, zostaw `task_ids` i `suggested_task_ids` puste i zaplanuj osobne zadanie w `config/tasks.toml`.
- Reguly z `knowledge/rules.jsonl` wspieraja analize i uzasadnienie planu. Nie wolno traktowac ich jako automatycznej zgody na wdrozenie zmian.
- `rules.jsonl` jest zrodlem prawdy. LanceDB, gdy zostanie dodane, ma byc tylko indeksem semantycznym odbudowywanym z JSONL.
- Po zmianach w `rules.jsonl` odswiez indeks:

```powershell
python gads.py wiedza indeksuj
```

- Wyszukiwanie semantyczne:

```powershell
python gads.py wiedza szukaj-ai "zapytanie opisowe"
```

- Kazda regula powinna miec metadane: `status`, `created_at`, `updated_at`, `source_file`, `duplicate_of`, `supersedes`.
- Nie kasuj regul recznie przy porzadkowaniu bazy. Zmieniaj status:

```powershell
python gads.py wiedza archiwizuj --rule-id "<id_reguly>"
python gads.py wiedza aktywuj --rule-id "<id_reguly>"
python gads.py wiedza duplikat --rule-id "<id_reguly>" --duplicate-of "<id_reguly_nadrzednej>"
```

- Po imporcie sprawdz wynik:

```powershell
python gads.py wiedza szukaj "temat"
python gads.py wiedza propozycje
python gads.py wiedza reguly --task check_pla_settings
python gads.py wiedza lista --topic shopping
python gads.py wiedza statystyki
```
