From 16a38d9740fc56df71ba1418a576ecb0defdf2ac Mon Sep 17 00:00:00 2001 From: Michal Matuszewski <90936684+MichalMatu@users.noreply.github.com> Date: Mon, 24 Aug 2026 19:11:41 +0200 Subject: [PATCH 1/6] Cleanup stale development handoff notes --- continue_test.md | 301 ----------------------------------------------- 1 file changed, 301 deletions(-) delete mode 100644 continue_test.md diff --git a/continue_test.md b/continue_test.md deleted file mode 100644 index d7183830..00000000 --- a/continue_test.md +++ /dev/null @@ -1,301 +0,0 @@ -# Dwie maszyny deweloperskie — Mac M1 + Raspberry Pi 5 - -Projekt **growbox-ml-controller** można rozwijać **niezależnie** na: - -| Maszyna | Rola typowa | -|---------|-------------| -| **MacBook Air M1** | Kod, panel UI, szybki build/flash, testy lokalne | -| **Raspberry Pi 5 (16 GB)** | Build/flash, testy serial **24/7**, długie audyty (tmux) | - -Synchronizacja kodu: **git** (`pull` / `push`). Każda maszyna ma **własny** `.venv`, `build/`, `sdkconfig` i instalację ESP-IDF — artefakty buildu **nie są współdzielone** (są w `.gitignore`). - ---- - -## Zasady współpracy (obie maszyny) - -1. **Przed pracą:** `git pull` na maszynie, na której zaczynasz. -2. **Po zmianach:** commit + push; druga maszyna robi `git pull`. -3. **ESP32 pod USB:** fizycznie podłączony do **jednej** maszyny naraz (przenosisz kabel lub zostawiasz na Pi pod audyty). -4. **Port serial:** ustaw per maszyna (patrz tabela poniżej). -5. **Panel + audyt serial:** tylko **jeden** klient na port — przed audytem `disconnect` panelu lub nie uruchamiaj panelu. -6. **Checkpointy audytu** (`build/audit/*.jsonl`): opcjonalnie `scp`/`rsync` między maszynami — nie ma ich w git. - -### Porty i zmienne - -| | MacBook Air M1 | Raspberry Pi 5 | -|--|----------------|----------------| -| Port typowy | `/dev/cu.usbmodem1101` | `/dev/ttyACM0` lub `/dev/ttyUSB0` | -| `make flash` | `PORT=/dev/cu.usbmodem1101 make flash` | `PORT=/dev/ttyACM0 make flash` | -| Python / audyt | `export GROWBOX_BOARD_PORT=/dev/cu.usbmodem1101` | `export GROWBOX_BOARD_PORT=/dev/ttyACM0` | -| Lista portów | `make ports` | `make ports` | - ---- - -## Setup jednorazowy — MacBook Air M1 - -```bash -cd ~/Documents/PlatformIO/Projects/ml # lub inna ścieżka -git clone . # jeśli świeży klon -git checkout main - -make setup-dev # venv + pre-commit (opcjonalnie setup bez -dev) - -# ESP-IDF 5.5.1 (jeśli jeszcze nie ma) -mkdir -p ~/esp && cd ~/esp -git clone -b v5.5.1 --recursive https://github.com/espressif/esp-idf.git -cd esp-idf && ./install.sh esp32s3 -# w każdej nowej sesji terminala: -source ~/esp/esp-idf/export.sh -# lub z katalogu repo: -source scripts/source_idf.sh -``` - -### Pełny flow na Macu - -```bash -source scripts/source_idf.sh -make check-fast # lint / format -make test # pytest + host C++ -PORT=/dev/cu.usbmodem1101 make flash -export GROWBOX_BOARD_PORT=/dev/cu.usbmodem1101 -make test-board # E2E na płytce - -make panel # http://127.0.0.1:8765 -python -m tools.ml.board_engine_audit --matrix-only -python -m tools.ml.panel_endpoint_audit - -make train-quick # smoke ML (CI) -make probe-sim # fizyka symulatora -``` - ---- - -## Setup jednorazowy — Raspberry Pi 5 (16 GB) - -Pi ma **ten sam komplet** możliwości co Mac: build, flash, panel, trening, audyty. - -### System (Debian / Raspberry Pi OS 64-bit) - -```bash -sudo apt update -sudo apt install -y git wget flex bison gperf python3 python3-pip python3-venv \ - cmake ninja-build ccache libffi-dev libssl-dev dfu-util libusb-1.0-0 \ - build-essential - -sudo usermod -aG dialout $USER -# wyloguj i zaloguj — dostęp do /dev/ttyACM* -``` - -### Repo + Python - -```bash -git clone https://github.com/MichalMatu/growbox-ml-controller.git ~/ml -cd ~/ml -git checkout main - -make setup-dev -``` - -### ESP-IDF 5.5.1 na Pi (aarch64) - -```bash -mkdir -p ~/esp && cd ~/esp -git clone -b v5.5.1 --recursive https://github.com/espressif/esp-idf.git -cd esp-idf -./install.sh esp32s3 -``` - -Dodaj do `~/.bashrc` (opcjonalnie): - -```bash -alias get_idf='. ~/esp/esp-idf/export.sh' -``` - -Pierwszy `make build` na Pi trwa **dłużej** niż na Macu — to normalne. 16 GB RAM wystarcza z zapasem. - -### Pełny flow na Pi - -```bash -cd ~/ml -source scripts/source_idf.sh - -make build -PORT=/dev/ttyACM0 make flash # dostosuj PORT po: make ports - -export GROWBOX_BOARD_PORT=/dev/ttyACM0 -make test-board -make test-board-exhaustive # długi audyt — patrz sekcja poniżej - -# panel (opcjonalnie; nie razem z audytem na tym samym porcie) -make panel -``` - -Testy host C++ i pełny quality gate: - -```bash -make test-host -make check-push # jak przed push — wolniejsze, wymaga IDF -``` - ---- - -## Kontynuacja audytu exhaustive (stan na migracji) - -Audyt zatrzymany na Macu; wznawiany na Pi (lub ponownie na Macu — ten sam checkpoint). - -| Element | Wartość | -|---------|---------| -| Test | `exhaustive_board_audit` | -| Plan | **460 395** case (`--skip-heavy-over 50000`) | -| Zatrzymano na | **6510** case (~1,4%) — profil **P03** | -| Ostatni case | `P03/X[…]` — `status=ok`, `errors=0` | -| Checkpoint | `build/audit/exhaustive_checkpoint.jsonl` | -| Log | `build/audit/exhaustive_board.log` | -| Raport (koniec) | `build/audit/exhaustive_board_audit.json` | - -### Skopiuj checkpoint Mac → Pi (jednorazowo) - -Z Maca: - -```bash -scp /Users/michal/Documents/PlatformIO/Projects/ml/build/audit/exhaustive_checkpoint.jsonl \ - pi@:~/ml/build/audit/ -# opcjonalnie: -scp build/audit/exhaustive_board.log pi@:~/ml/build/audit/ -``` - -Na Pi: - -```bash -mkdir -p ~/ml/build/audit -wc -l ~/ml/build/audit/exhaustive_checkpoint.jsonl # oczekiwane: 6510 -``` - -### Wznowienie 24/7 na Pi (tmux) - -```bash -tmux new -s audit -cd ~/ml -source scripts/source_idf.sh # nie wymagane do audytu, ale wygodne w jednej sesji - -export GROWBOX_BOARD_PORT=/dev/ttyACM0 - -.venv/bin/python -m tools.ml.exhaustive_board_audit \ - --port "$GROWBOX_BOARD_PORT" \ - --skip-heavy-over 50000 \ - --checkpoint build/audit/exhaustive_checkpoint.jsonl \ - --report build/audit/exhaustive_board_audit.json \ - 2>&1 | tee -a build/audit/exhaustive_board.log -``` - -Odłączenie SSH: `Ctrl+B`, `D`. Powrót: `tmux attach -t audit`. - -Alternatywa: `export GROWBOX_BOARD_PORT=/dev/ttyACM0 && make test-board-exhaustive` - -### Postęp i PASS/FAIL - -```bash -wc -l build/audit/exhaustive_checkpoint.jsonl -tail -f build/audit/exhaustive_board.log -``` - -- Wznowienie pomija case ze `status: ok` w checkpoint. -- **PASS** = `error_count: 0` w `exhaustive_board_audit.json`. -- **WARN** = słabe miejsca ML — do przejrzenia, nie blokuje flashu. - -Szacowany czas od 6510: **~46 h** @ ~380 ms/case. - ---- - -## Typowy dzień pracy na dwóch maszynach - -### Scenariusz A — kodujesz na Macu, Pi testuje w tle - -```bash -# Mac -git pull -# ... edycja kodu ... -make check-fast && make test -git commit -am "..." && git push - -# Pi (SSH) -git pull -# jeśli zmiana firmware: -source scripts/source_idf.sh && PORT=/dev/ttyACM0 make flash -# audyt już leci w tmux — nie restartuj bez potrzeby -``` - -### Scenariusz B — kodujesz na Pi - -Ten sam schemat — `git push` z Pi, `git pull` na Macu. Obie maszyny mają ESP-IDF i `make flash`. - -### Scenariusz C — przenosisz ESP z Pi na Mac - -1. Zatrzymaj audyt / monitor na Pi. -2. Odłącz USB, podłącz do Maca. -3. `make ports` — nowy port. -4. `PORT=... make flash` na Macu. - ---- - -## Co jest / nie jest w git - -| W git | Lokalnie per maszyna | -|-------|----------------------| -| Źródła, schema, Makefile | `.venv/` | -| Wyeksportowane nagłówki modelu | `build/` (IDF, host-tests, audit) | -| `config/idf/sdkconfig.defaults*` | `sdkconfig` (generowany przy build) | -| | `~/esp/esp-idf/` | -| | checkpointy `build/audit/*.jsonl` | - -**Nie commituj** `build/`, `sdkconfig`, `.venv`. Checkpoint audytu przenosisz `scp` tylko gdy wznawiasz na drugiej maszynie. - ---- - -## Po zakończeniu exhaustive - -1. Regres na maszynie z ESP: - ```bash - export GROWBOX_BOARD_PORT= - python -m tools.ml.board_engine_audit --matrix-only - python -m tools.ml.panel_endpoint_audit # wymaga panelu - ``` -2. Rozszerzenia (dowolna maszyna z ESP + czas): - - `make test-board-validity-matrix` — 32 768 masek validity - - `make train-full` + `make flash` — po dopracowaniu symulatora - - exhaustive bez `--skip-heavy-over` — profile P05/P06 (bardzo długo) - ---- - -## Typowe problemy - -| Problem | Rozwiązanie | -|---------|-------------| -| `ESP-IDF niedostępne` | `source ~/esp/esp-idf/export.sh` lub `source scripts/source_idf.sh` | -| `Permission denied` na `/dev/ttyACM0` (Pi) | `usermod -aG dialout`, re-login | -| `multiple access on port` | jeden klient serial; panel disconnect lub stop audytu | -| Build na Pi wolny | pierwszy build długi; `ccache` już w zależnościach apt | -| Różny `sdkconfig` między maszynami | OK — generowany lokalnie z `config/idf/sdkconfig.defaults*` | -| Konflikt po `git pull` | rozwiąż merge; **nie** kopiuj `build/` między maszynami | - ---- - -## Szybka ściąga komend - -```bash -# obie maszyny -source scripts/source_idf.sh -make setup-dev # raz -git pull / git push # sync - -# flash (PORT per maszyna) -PORT= make flash - -# audyt (GROWBOX_BOARD_PORT per maszyna) -export GROWBOX_BOARD_PORT= -make test-board-exhaustive - -# panel -make panel # :8765 -make ports # lista USB -``` From 19d39e0d1750a3dd557fc05df230a03f33263201 Mon Sep 17 00:00:00 2001 From: Michal Matuszewski <90936684+MichalMatu@users.noreply.github.com> Date: Mon, 24 Aug 2026 19:11:48 +0200 Subject: [PATCH 2/6] Remove obsolete v2 planning document --- docs/plan.md | 432 --------------------------------------------------- 1 file changed, 432 deletions(-) delete mode 100644 docs/plan.md diff --git a/docs/plan.md b/docs/plan.md deleted file mode 100644 index 1b5184c9..00000000 --- a/docs/plan.md +++ /dev/null @@ -1,432 +0,0 @@ -# Plan prac — kontrakt v2 i sterowanie - -Żywy dokument: kolejność prac i ustalenia z analizy panelu / symulatora (2026-07). - -**Źródło prawdy techniczne:** v1 w kodzie — [`environment-controller.json`](../schemas/environment-controller.json); **I/O v2 definitywne** — tabelka w [IO_MAP.md](IO_MAP.md) → *Kontrakt v2*. - -**Indeks dokumentacji** - -| Plik | Po co | -|------|--------| -| Ten plik | Plan, decyzje, co dalej | -| [IO_MAP.md](IO_MAP.md) | Mapowanie sprzętu → sloty kontraktu | -| [DATA_CONTRACT.md](DATA_CONTRACT.md) | Zasady kontraktu (krótko) | -| [ARCHITECTURE.md](ARCHITECTURE.md) | Warstwy kodu | -| [MODEL_PIPELINE.md](MODEL_PIPELINE.md) | Trening, export, **fidelity symulatora** | -| [PORTING_TO_LITEGRAPH.md](PORTING_TO_LITEGRAPH.md) | Integracja z GrowClip (później) | -| [README.md](../README.md) | Setup, build, panel, serial | - ---- - -## Model złożoności — jak nie płatać - -Growbox ma **setki** sprzężeń (T, RH, gleba, fan, zewnątrz, lampa, CO₂…). **Nie wypisujemy ich w dokumentacji** ani w kontrakcie JSON — inaczej dokumentacja się nigdy nie kończy i rozjeżdża z kodem. - -```text -ZAMKNIĘTE (nie ruszamy bez v2.1) → sloty I/O: sensing + 10 wyjść ML [IO_MAP.md] -JEDNO ŹRÓDŁO PRAWDY FIZYKI → tools/ml/simulator.py (+ ten sam model w DummyEnvironmentSimulator) -KRÓTKA LISTA TWARDYCH REGUŁ → SafetySupervisor (~10–15 reasonów, nie setki ifów w docs) -HARMONOGRAM / NODEFLOW → fotoperiod, opcj. dogrzewanie lampą — poza ML -ML → uczy się koordynacji z trajektorii symulatora (nie z README) -``` - -| Pytanie | Odpowiedź | -|---------|-----------| -| Czy muszę opisać każdą zależność, o której pomyślę? | **Nie** — tylko dodać **składnik** do symulatora, jeśli brakuje w trajektoriach. | -| Co robią luźne akapity o lampie / fanie / grzałce w docs? | **Przykłady** kategorii (termika, wymiana z zewnątrz), nie komplet reguł. | -| Skąd wiem, że nic ważnego nie ginie? | Iteracja: symulator → trening → **replay na żywym boxie** → korekta współczynników. | -| Co jest „domknięte” na dziś? | **Sensing** + **wyjścia ML** + mix & match. Reszta = **Faza 2–4 (kod)**. | - -**Nie dokładamy** kolejnych akapitów zależności do `IO_MAP.md` — tylko nowe **sloty** (v2.1+). Zachowanie termiczne → symulator + safety + issue/PR, nie kolejna sekcja w mapowaniu sprzętu. - -Szkic polityk termicznych (lampa, grzałka, fan vs `outside_*`) — implementacja Fazy 2–3: [poniżej *Symulator — termodynamika*](#symulator--termodynamika-growboxa-trening) i safety; szczegóły w kodzie, nie w checklistie czujników. - ---- - -## Wizja produktu — komercyjny sterownik - -Ten projekt nie jest „kontrolerem jednego growboxa użytkownika”. Celem jest **sterownik na sprzedaż**: -konfigurowalny, przewidywalny, z jasnym safety — z opcjonalną warstwą ML jako wartością dodaną. - -Repozytorium `growbox-ml-controller` to dziś **rdzeń decyzyjny** (kontrakt, encoder, model, safety, demo). -Produkt końcowy to opakowanie: panel, konfiguracja stref, integracja czujników (np. Tuya Zigbee), -mostek aktuatorów, wsparcie, firmware na ESP — ścieżka GrowClip / LiteGraph ([PORTING_TO_LITEGRAPH.md](PORTING_TO_LITEGRAPH.md)). - -### Hobby vs produkt - -| Hobby (jedna instalacja) | Produkt komercyjny | -|--------------------------|-------------------| -| Znam swój sprzęt | Klient: **1–4 strefy**, różna konfiguracja, część wyłączona | -| „Działa u mnie” | **Przewidywalne** zachowanie + safety + opis w UI | -| ML można ciągle poprawiać ad hoc | **Jedna linia firmware** + konfiguracja, nie fork na klienta | -| Integracja „u mnie w HA” | Oficjalna ścieżka: czujnik → hub → mostek → sloty kontraktu | -| Brak sprzętu = nie istnieje | **Mix & match:** każdy slot osobno — czujnik `validity: false`, aktuator `available: false`; reszta działa | - -### Warstwy produktu - -```text -Warstwa klienta panel / aplikacja — ile stref aktywnych (1–4), cele, safety -Warstwa integracji Zigbee (Tuya), przekaźniki, pompy — GrowClip / Nodeflow -Warstwa decyzji FeatureEncoder + ModelRuntime + SafetySupervisor ← to repo -Warstwa sprzętu ESP32, GPIO, obudowa, certyfikacja (poza tym repo) -``` - -- **Safety i reguły** — to, co klient traktuje jako „bezpieczny sterownik”; muszą działać nawet przy słabym ML. -- **ML** — propozycja sterowania klimatem globalnym; w produkcie może być domyślne lub warstwa Pro (decyzja biznesowa później). -- **Symulator / trening** — R&D wewnętrzne: **możliwie wierna termodynamika growboxa** (złożone sprzężenia T↔RH↔gleba); klient widzi kontrakt i zachowanie, nie pipeline Keras. - -### SKU i konfiguracja (v2) - -| Element produktu | Decyzja techniczna | -|------------------|-------------------| -| Do **4 donic** na jednym sterowniku | Max **4 strefy** w kontrakcie | -| Strefa = donica | **Wilgotność gleby (wym.) + pompa**; temp. gleby **opcjonalna** per strefa | -| Klient ma dziś 1 donicę | Włączona **strefa 1**; 2–4 `available: false` | -| Czujniki gleby | Tanie (tylko wilg.) lub premium (wilg. + temp., np. Tuya) — ten sam kontrakt, różne `validity` | -| Klimat boxa | Globalne: temp / RH / CO₂ — **każdy slot osobno** ☑/☐ (+ zewnątrz, to samo) | -| Enrichment CO₂ | Butla + **zawór dozujący** — osobne wyjście; dozowanie głównie gdy **fan wyłączony** | -| Aktuary globalne | Grzałka, fan, nawilżacz, osuszacz, chłodzenie, **CO₂ zawór** — slot + `available` | - -### Wymagania komercyjne (do wdrożenia poza samym ML) - -- **Profil konfiguracji** — liczba aktywnych stref bez przebudowy firmware. -- **Profile czujników gleby** — „wilgotność only” vs „wilgotność + temp.”; lista wspieranych integracji (Tuya, ADC, …). -- **Nieaktualne dane Zigbee** — ostatni raport + `validity` / staleness (bateria, raport co kilka minut). -- **Powody safety** w UI (`safety_reason`, `output_reason_masks`) — wsparcie i debug u klienta. -- **Wersja kontraktu / modelu** w logu i panelu — zgodność OTA i support. - -### Konsekwencje dla planu prac - -1. Kontrakt **v2** projektujemy pod produkt (strefy, pełne sloty, `available`), nie pod jedną instalację. -2. **Nie** dopieszczać modelu v1 — klient dostanie v2 po domknięciu I/O. -3. Panel i JSON scenariusza muszą odzwierciedlać **strefy** i włącz/wyłącz sprzętu jak w finalnym UI. -4. Integracja LiteGraph to **produkcja**, demo UART to **laboratorium**. - ---- - -## Ustalenia (nie retrenuj v1 na poważnie) - -### Jak działa sterowanie - -```text -Czujniki + cele + konfiguracja - → FeatureEncoder (cechy 0..1) - → ModelRuntime (propozycja raw) - → SafetySupervisor (safe + powody) - → mostek / symulator -``` - -- **Model** tylko proponuje wartości 0–1. -- **Safety** ma twarde reguły niezależne od modelu. -- **Checkbox „w systemie”** (`available`) = urządzenie wyłączone w scenariuszu; model widzi brak, safety wymusza 0. -- **Validity czujnika** = brak odczytu; encoder podstawia default + maskę. - -### Co widać na żywo (v1, model `quick`) - -| Objaw | Przyczyna | -|-------|-----------| -| Fan ~13% mimo `minimum_command ≈ 0` | Bias wgranej sieci (`raw.fan ≈ 0.13`), nie safety. Test MAE fana ~0.20. | -| Pompa ~9% przy glebie 100% | Ten sam słaby model; teacher przy pełnej glebie daje `irrigation=0`. | -| Mruganie `bez zmian` / `≠` na pompie | Rytm symulatora: model cały czas chce ~9%, co kilka kroków safety puszcza impuls vs `pump_minimum_interval`. | -| `fan min` w ustawieniach nic nie zmienia | Minimum to podłoga; model i tak proponuje ~13%. | - -**Wniosek:** teacher i symulator treningowy są sensowne; **wgrany MLP v1 (`quick`) jest za słaby i uczył się na niepełnym kontrakcie**. Retrening na v1 przed domknięciem I/O to zmarnowany effort. - -### Luka v1: firmware vs model - -| Element | Panel / firmware | Kontrakt ML (40 cech) | -|---------|------------------|------------------------| -| `outside_co2_ppm` | tak | **nie** (CO₂ zewn. w treningu = stałe 420 ppm) | -| osuszacz | nie | nie | -| chłodzenie / klimatyzator | nie | nie | -| blokada pompy przy pełnej glebie | nie | — (brak reguły safety) | - ---- - -## Cel: kontrakt v2 w docelowej formie - -Pełny zestaw **nawet gdy sprzętu fizycznie nie ma** — każde urządzenie ma `available`, każdy czujnik ma `validity`. Trening losuje scenariusze włącz/wyłącz, żeby model uczył się obu trybów. - -### Klimat wewnątrz growboxa (plan v2) — zamknięta lista - -**Globalne** (jeden zestaw na cały box) — **nic więcej na start v2**: - -| Czujnik | v2 | Uwagi | -|---------|-----|--------| -| `air_temperature_c` | **tak** | korona / środek komory | -| `air_humidity_pct` | **tak** | | -| `co2_ppm` | **opcj.** | slot zawsze; `validity: false` bez czujnika (np. profil 2× TP357) | -| `nutrient_solution_temperature_c` | **opcjonalnie** | DS18B20 w zbiorniku odżywki; **≠** temp. gleby w donicy | - -Nie dodajemy na v2: **czujnik nasłonecznienia / PPFD** (zastępuje stan lampy), temp. liścia, VPD osobno, EC/pH (v2.1 / hydro). Światło = harmonogram, nie wyjście ML. - -**Temp. odżywki vs temp. gleby:** osobne pola. Safety (i opcjonalnie ML) porównuje oba przed podlewaniem — unikaj zimnego nawozu na rozgrzany substrat (konfigurowalny max ΔT lub min. temp. roztworu). Głównie **safety**; ML widzi obie cechy w treningu. - -**Zewnątrz** (zamknięte na v2): `outside_temperature_c`, `outside_humidity_pct`, `outside_co2_ppm` — każdy ☑/☐ — [IO_MAP.md](IO_MAP.md) → *Sensing v2*. - -**Roadmap** (czujniki, aktuary, safety, poza ML): [IO_MAP.md](IO_MAP.md) → *Świadomie poza v2* oraz sekcja *Roadmap produktu* poniżej. - -### Strefy podlewania — max 4 (ustalone 2026-07) - -**Jedna strefa = jedna donica w tym samym growboxie** — wspólne powietrze (`air_*`, `co2_ppm`); per donica: czujnik gleby + pompa (indeks 1…4). Podlewanie **zawsze** wpływa na RH (i pośrednio na T) w całej komorze — wielkość efektu zależy od scenariusza; symulator v2 modeluje sprzężenia T↔RH↔gleba↔fan↔zewnątrz. **ML** uczy sterowania w tym układzie, nie zastępuje fizyki w runtime (fizyka = symulator treningowy + reguły safety). - -| Per strefa `pots[i]` | Wymagane? | Uwagi | -|----------------------|-----------|--------| -| `soil_moisture_pct` + `validity` | **tak** (gdy strefa aktywna) | Podlewanie; źródło dowolne (ADC, Zigbee, Tuya…) | -| `soil_temperature_c` + `validity` | **nie** | **Osobne, niepowiązane wejście** — np. **DS18B20** (1-Wire) | -| `target_soil_moisture_pct` | tak | cel tej donicy | -| pompa + `available`, parametry | tak | `irrigation_pot_N` | -| `previous_irrigation` | tak | per strefa | - -**Wilgotność i temp. gleby = dwa niezależne wejścia** (osobne ścieżki JSON, osobne `validity`, osobni driverzy w mostku). **Brak** założenia „jeden moduł 2-w-1”: - -```text -Strefa 1: soil_moisture ← sonda wilgotności validity_moisture - soil_temperature ← DS18B20 w donicy validity_temperature (niezależnie!) -``` - -Przykłady kombinacji: - -| Wilgotność | Temp. gleby | validity | -|------------|-------------|----------| -| Tuya Zigbee | brak | moist=true, temp=false | -| ADC / tanie | DS18B20 | oba true, **różne hardware** | -| Tuya 2-w-1 | ten sam moduł | oba true — mostek wypełnia oba sloty | - -Szkic pól: [`schemas/environment-controller.json`](../schemas/environment-controller.json) (draft, nie w CI). - -Mostek ustawia `validity`; encoder podstawia default + maskę (jak przy innych czujnikach). Safety i podlewanie **nie zależą** od temp. gleby. Reguły na temp. gleby (np. zimna gleba) tylko gdy `soil_temperature_c` valid. - -Nieużywane strefy: `pot.available = false`. Trening losuje: strefa z/bez temp. gleby, 1–4 aktywne strefy. - -**Wyjścia ML:** `irrigation_pot_1` … `irrigation_pot_4`. Safety: `irrigation_pot_N_pulse_s` per strefa. - -### Wyjścia ML v2 (zamknięte — 10 slotów) - -Tabela sprzętu: [IO_MAP.md](IO_MAP.md) → *Wyjścia ML*. Szkic: `schemas/environment-controller.json`. - -| Wyjście | v1 | v2 | Uwagi | -|---------|----|----|--------| -| `heater` | tak | tak | | -| `fan` | tak | tak | Wymiana powietrza — **konflikt z dozowaniem CO₂** (patrz niżej) | -| `humidifier` | tak | tak | | -| `dehumidifier` | nie | **tak** | Osobne wyjście (potwierdzone) | -| `cooler` | nie | **tak** | Osobno od grzałki i osuszacza (potwierdzone) | -| `co2_doser` | nie | **tak** | Binarny impuls; `available` gdy brak butli | -| `irrigation_pot_1…4` | jedna pompa | **tak** | 0–4 aktywnych; per strefa safety | -| światło | nie | **poza ML** | Harmonogram + `lights_active` jako **wejście**; obciążenie cieplne lampy w symulatorze; OFF przy alarmie T | - -### Dozowanie CO₂ z butli (ustalone 2026-07) - -**Sprzęt:** butla CO₂ + elektrozawór (on/off). Pomiar `co2_ppm` zostaje **czujnikiem**, zawór to **aktuator**. - -**Logika produktowa:** CO₂ dozujemy tylko w „oknie”, gdy wentylacja **nie wyrzuca** gazu — typowo **fan wyłączony** (lub poniżej progu). Wentylator służy do wymiany / chłodzenia; enrichment to osobna faza. - -```text -Model / reguła proponuje co2_doser - → Safety: jeśli safe.fan > próg → co2_doser = 0 (powód: fan_venting_co2) - → Safety: jeśli co2_ppm ≥ cel → co2_doser = 0 - → Safety: alarm temp. / brak czujnika CO₂ → blokada - → tylko gdy `lights_active` z harmonogramu (bez czujnika PPFD) -``` - -| Warstwa | Rola | -|---------|------| -| **Safety (twarde)** | Brak CO₂ przy włączonym wencie; przy CO₂ ≥ cel; przy alarmach | -| **ML (miękkie)** | Kiedy w oknie fan=0 — ile / czy dawkować (jeśli w ogóle w ML) | -| **Konfiguracja** | `co2_doser`: przepływ / czas impulsu, min. przerwa między dawkami, próg „fan uznany za włączony” | - -W treningu symulator musi modelować: dawka CO₂ podnosi `co2_ppm`, fan obniża w stronę `outside_co2`. Teacher uczy sekwencji „najpierw fan off, potem doza”. - -**Nie mylić:** `co2_ppm` (czujnik) ≠ `co2_doser` (zawór). Cel `target_co2_ppm` już jest w kontrakcie. - -### Safety (plan — poza checkboxami) - -Reguły „nigdy”, nawet gdy model chce inaczej: - -| Reguła | Status v1 | v2 | -|--------|-----------|-----| -| max / alarm temperatury, min fan przy alarmie | tak | utrzymać | -| przerwa między impulsami pompy | jedna pompa | **osobny licznik per strefa** | -| gleba strefy N ≥ cel → pompa N = 0 | **nie** | **dodać (per strefa)** | -| **ΔT roztwór–gleba** zbyt duże → blokada pompy N | nie | **dodać** (gdy oba `valid`) | -| roztwór zbyt zimny → blokada podlewania | nie | **dodać** (próg w `SafetyConfig`) | -| **fan > próg → co2_doser = 0** | nie | **dodać** (`fan_venting_co2` / podobny reason) | -| **co2_ppm ≥ cel → co2_doser = 0** | nie | **dodać** | -| przerwa między dawkami CO₂ | — | jak u pompy — min. interwał | -| deadband fana (np. raw < 5% → 0) | nie | opcjonalna łata przed retreningiem | -| dwell binarnych (grzałka, nawilżacz, …) | częściowo | rozszerzyć o nowe aktuary | - -### Co do ML, co poza ML - -| Warstwa | Przykłady | -|---------|-----------| -| **ML** | Sterowanie przy **sprzężeniach** T↔RH↔gleba (4 donice)→powietrze↔fan↔zewnątrz↔CO₂ — który aktuator, kiedy i ile; uczenie na symulatorze z tą fizyką | -| **Symulator (trening)** | Dynamika growboxa — **możliwie blisko** realnej termodynamiki komory (patrz sekcja poniżej); źródło trajektorii dla ML i teacher | -| **Safety** | Alarmy, pełna gleba, niedostępny czujnik, wymuszenie 0 na `available=false` | -| **Harmonogram / Nodeflow** | Światło dzień/noc, tryby użytkownika | -| **Mostek sprzętowy** | 1× `fan` → kilka fizycznych wentylatorów | - -**Na płytce w runtime:** czujniki dają **stan** (nie ML); ML **proponuje** wyjścia 0–1; safety **tnie**; mostek wykonuje. ML nie liczy fizyki zamiast czujników — ale bez ML trudno sensownie koordynować wiele sprzężonych aktuatorów (np. pompa vs nawilżacz vs fan przy tym samym celu RH). - -### Symulator — termodynamika growboxa (trening) - -Growbox to **jedna komora** z **wieloma sprzężonymi** procesami: temperatura i wilgotność powietrza wpływają na siebie nawzajem; podlewanie donic zmienia glebę **i** RH w całym boxie; suchość i ciepło przyspieszają parowanie z substratu **nieliniowo**; fan wymienia powietrze z zewnątrz; grzałka, osuszacz, chłodzenie i CO₂ dokładają kolejne pętle. Sterowanie tym regułami if/else jest kruche — dlatego ML uczy się na trajektoriach z symulatora. - -**Cel symulatora:** możliwie **blisko** odwzorować realne zachowanie termodynamiczne growboxa — wystarczająco dobrze, żeby teacher i sieć uczyły się **właściwych** zależności przyczynowych (np. pompa vs nawilżacz przy tym samym celu RH). To **nie** CFD ani cyfrowy twin laboratoryjny: model **zgrupowany** (objętość komory, 4 donice, składowe co krok Δt), kalibrowany parametrami scenariusza i iteracyjnie porównywany z żywym boxem. - -| Gdzie piszemy co | Zakres | -|------------------|--------| -| **Kontrakt / [IO_MAP.md](IO_MAP.md)** | sloty I/O, mix & match — **bez** równań fizycznych | -| **`tools/ml/simulator.py`** (+ docelowo ten sam model w `DummyEnvironmentSimulator`) | **cała dynamika** — jedyne źródło prawdy sprzężeń | -| **Teacher** | koszt / heurystyki celów na trajektoriach z symulatora | -| **Safety** | twarde granice niezależne od modelu | -| **Runtime na płytce** | **czujniki** = stan; symulator **nie** działa w produkcji | - -**Sprzężenia do odwzorowania w v2** (wzory w kodzie, nie lista reguł w dokumentacji): - -1. **Donica → powietrze** — **suma po aktywnych strefach** (0–4, nie zawsze cztery): parowanie / transpiracja do wspólnego `air_humidity_pct`; per slot wilgotność gleby, temp. gleby (gdy valid), RH i T powietrza; wyłączona strefa = brak składnika (jak `validity: false` / `pot.available: false`). -2. **T ↔ RH komory** — wymiana z `outside_*` (fan, przecieki), nawilżacz / osuszacz / chłodzenie, **ciepło utajone** parowania (RH ↑ może iść w parze z krótkim T ↓). -3. **Podlewanie** — dyskretny impuls per strefa → gleba N + natychmiastowy i utajony składnik evap. -4. **CO₂** — `co2_doser`, wymiana przez fan w stronę `outside_co2_ppm`, uproszczony metabolizm. -5. **Lampa (`lights_active`)** — gdy true: stałe lub konfigurowalne `lights_max_heat_w` w bilansie T (jak grzałka); wyłączenie lampy przy przekroczeniu progu T → **safety**, nie wyjście ML. -6. **Fan vs `outside_temperature_c`** — wymiana ciepła już w modelu wymiany powietrza; teacher/safety: przy grzaniu i `outside_T` ≪ `inside_T` — nie wietrzyć na max (uchronić ciepło). - -v1 (`simulator.py`) ma już nieliniowe prototypy (`vapor_deficit`, `temperature_factor`). **Faza 2** rozszerza o 4 donice, temp. gleby, evap po podlewaniu, **ciepło lampy** i politykę fan/zewnątrz w teacher; **Faza 4** trening na tym symulatorze. Jakość ML = jakość symulatora × teacher. - -**Światło — nie tylko symulator:** twarde „za gorąco → lampa OFF” musi być w **SafetySupervisor + mostek** (ochrona roślin). „Za zimno → lampa ON jako dogrzewanie” to **harmonogram / Nodeflow** (opcjonalny tryb), opisane w [IO_MAP.md](IO_MAP.md). Symulator sam nie zastąpi safety — modeluje **skutki**, safety pilnuje **limitów**. - -**Brak grzałki / słaba grzałka / lampa / fan vs zewnątrz** — przykłady sprzężeń termicznych; pełna lista = kod symulatora, nie dokumentacja. - -**Walidacja:** testy kierunku (sucho+ciepło > wilgotno+zimno), potem replay na prawdziwym sprzęcie i korekta parametrów — bez wypisywania każdej pary zależności w osobnych dokumentach. - ---- - -## Roadmap produktu — świadomie poza v2 - -Skrót „mentalnego obrazu”: co **jest** w v2, a czego **świadomie nie ma** w kolejnych wersjach (nie przypadkowe luki). Szczegóły slotów: [IO_MAP.md](IO_MAP.md). - -### Linia czasu - -```text -v2 (teraz) substrat, 4 strefy, klimat, CO₂ butla, safety per strefa -v2.1 hydro (EC/pH), zalanie, PPFD, opcj. VPD w ML -v2.2+ liść IR, wylot wentylacji, outdoor / premium -poza kontraktem harmonogram, Nodeflow, interlocki, support, LiteGraph -``` - -### v2 — zakres zamknięty - -| Obszar | W v2 | Poza v2 (świadomie) | -|--------|------|---------------------| -| Czujniki wewnątrz | temp., RH; CO₂ opcj.; opcj. temp. zbiornika; gleba ×4 | PPFD, liść, EC/pH | -| Czujniki zewnątrz | temp., RH; CO₂ opcj. przy wlocie | wylot, stacja pogodowa | -| Aktuary | 6 globalnych + 4 pompy + `co2_doser` | dimmer LED, fan×2 w ML, mata/donica | -| Światło | harmonogram → `lights_active` | wyjście ML, czujnik nasłonecznienia | -| ML | propozycja klimatu + podlewania | VPD jako cecha, retrening v1 | -| Safety | alarmy, pełna gleba, ΔT nawóz, fan↔CO₂ | zalanie (v2.1), dym (hardware) | - -### Dlaczego taka kolejność - -1. **v2** musi być kompletny SKU „growbox w ziemi” — przewidywalny bez drogich czujników. -2. **v2.1** rozszerza segment (hydro) i safety (zalanie), nie psuje kontraktu substratu. -3. **v2.2+** to upsell diagnostyczny — klient już ma działający rdzeń, dokłada czujniki. -4. **Harmonogram / UI / mostek** nigdy nie wchodzą do wektorów ML — stabilny podział warstw. - -### Otwarte na roadmapie (nie blokują v2) - -| Temat | Stan | Domyślna decyzja | -|-------|------|------------------| -| Dwa wentylatory fizyczne | pytanie otwarte | 1× `fan` ML + mapowanie w mostku | -| Klimatyzator vs osuszacz | do potwierdzenia | dwa osobne wyjścia (plan v2) | -| ML jako tier Pro | biznes | safety + reguły = zawsze; ML opcjonalnie | - ---- - -## Kolejność prac - -### Faza 0 — zamrożenie v1 (teraz) - -- [x] Zrozumieć objawy na panelu (bias modelu, nie UI) -- [x] Usunąć linię `impuls X s` z karty pompy (duplikat ustawień) -- [ ] **Nie** inwestować w dopieszczanie modelu v1 (`train-full` na starym kontrakcie) - -### Faza 1 — spec v2 (krótka) - -- [x] **Sensing v2** — zamknięte ([IO_MAP.md](IO_MAP.md) → *Sensing v2*) -- [x] **Wyjścia ML v2** — zamknięte (10 slotów) -- [ ] Potwierdzić pytania otwarte (poniżej) — tylko cele / wentylatory, nie czujniki -- [ ] Wypełnić [IO_MAP.md](IO_MAP.md) — kolumna „Twój sprzęt” (instalacja użytkownika) -- [ ] Dopisać w `environment-controller.json`: `lights_active`, targets, actuators w `features` (Faza 2) - -### Faza 2 — kontrakt v2 w kodzie (jeden duży PR) - -Kolejność wewnątrz fazy: - -1. `schemas/environment-controller.json` + generator → `EnvironmentSchema.h` -2. `EnvironmentTypes.h`, `FeatureEncoder`, `SafetySupervisor` -3. Symulator Python (`tools/ml/simulator.py`) — **termodynamika v2**; **do 4 slotów** donic (mix & match: `pots[N].available`, `validity`, `irrigation.available` — scenariusze losują 0–4 aktywne); teacher na tych trajektoriach -4. `DummyEnvironmentSimulator.cpp` — **ta sama fizyka** co Python; wire codec + panel (`form_schema.py`) -5. Testy kontraktu i hosta (wymiary, golden vectors — po retreningu) - -### Faza 3 — safety v2 - -- [ ] Gleba nasączona → blokada pompy -- [ ] Reguły dla osuszacza / chłodzenia (np. wzajemne wykluczenia z grzałką — jeśli potrzebne) -- [ ] Zachowanie przy `validity=false` na krytycznych czujnikach - -### Faza 4 — trening v2 - -- [ ] Dataset: losowe `available` / `validity` (jak dziś, rozszerzone) -- [ ] `make train-full` (nie `--quick`) -- [ ] Sprawdzić MAE per wyjście; odrzucić model z biasem „stałego 13%” -- [ ] Commit: schema + generated headers + golden vectors razem - -### Faza 5 — walidacja użytkowa - -- [ ] Panel: scenariusze z wyłączonymi aktuatorami -- [ ] Replay na płytce -- [ ] Dopiero potem LiteGraph ([PORTING_TO_LITEGRAPH.md](PORTING_TO_LITEGRAPH.md)) - ---- - -## Pytania otwarte (przed Fazą 2) - -1. ~~**Światło**~~ — **zamknięte:** harmonogram + `lights_active` / readback przekaźnika; **bez** czujnika nasłonecznienia na v2. -2. ~~**Klimatyzator vs osuszacz**~~ — **zamknięte:** `cooler` + `dehumidifier`, dwa osobne wyjścia. -3. **Dwa wentylatory** — domyślnie 1× `fan` ML + mapowanie w mostku (bez drugiego slotu ML). -4. **Cel wilgotności gleby** — jeden wspólny czy osobny per strefa? (plan: per strefa w `pots[i]`) - -## Zamknięte decyzje - -- Max **4 strefy** podlewania; strefa = czujnik gleby + pompa. -- **Sensing v2 zamknięte:** 15 slotów pomiarowych + `lights_active` — mix & match; lista w [IO_MAP.md](IO_MAP.md) → *Sensing v2*. -- **Wewnątrz boxa (globalnie):** `air_temperature_c`, `air_humidity_pct`, `co2_ppm` — każdy ☑/☐; bez dodatkowych czujników na v2. -- **Temp. gleby opcjonalna** per strefa (`validity` osobno); wilgotność gleby wymagana do logiki podlewania. -- **Temp. roztworu nawozowego** (`nutrient_solution_temperature_c`) — osobne od temp. gleby; DS18B20 w zbiorniku; safety przed „zimnym nawozem na ciepłą ziemię”. -- **CO₂:** czujnik `co2_ppm` **opcjonalny** (`validity: false` bez hardware); aktuator `co2_doser` (`available: false` bez butli); dozowanie zablokowane przy braku valid czujnika, przy wencie fanu lub CO₂ ≥ cel. -- **Światło:** bez PPFD; `lights_active` = wejście ML + termika w symulatorze; sterowanie przekaźnikiem **poza ML** (harmonogram, opcj. dogrzewanie, **safety OFF** przy upale). -- **Zewnątrz boxa:** 3 sloty przy wlocie — każdy ☑/☐ — zestaw zamknięty na v2. -- **Profil prosty:** 2× BLE TP357 (wewn. + zewn.) → 4 pomiary temp./RH, oba CO₂ `validity: false` — [IO_MAP.md](IO_MAP.md). -- **Wejścia czujnikowe v2:** **domknięte** — nie wracamy do listy slotów przed v2.1; roadmap → [IO_MAP.md](IO_MAP.md). -- **Świadomie poza v2:** PPFD, EC/pH, liść IR, zalanie, wylot wentylacji, światło w ML — roadmap v2.1 / v2.2+, nie scope Fazy 2. -- **I/O v2 definitywne (2026-07):** checklista 26 slotów w [IO_MAP.md](IO_MAP.md) → *Mix & match*; bez nowych czujników/wyjść ML w tej wersji. -- **Mix & match:** 26 slotów + opcj. `pots[N].available` — każdy osobno (`validity` / `available`); brak pakietów wymaganych. -- Dokładanie sprzętu = włączenie kolejnego indeksu strefy, bez nowego kontraktu. - ---- - -## Komendy (bez zmian) - -```bash -make panel # panel WWW -make train-quick # tylko smoke CI — nie produkcyjny model -make train-full # po v2 -python tools/schema/generate_environment_schema.py --check -``` - ---- - -## Notatka dla treningu v2 - -Teacher używa dyskretnej siatki akcji (np. fan: 0 / 0.25 / 0.5 / 0.75 / 1.0). Model regresuje na ciągłe sigmoidy — stąd biasy przy słabym treningu. Przy v2 rozważyć: więcej scenariuszy, `train-full`, rozkład `fan_minimum_command` obejmujący ~0, ewentualnie ważenie błędów per wyjście. From 8027be47cea06d2a56e3c9cbda6b0d4923215f41 Mon Sep 17 00:00:00 2001 From: Michal Matuszewski <90936684+MichalMatu@users.noreply.github.com> Date: Mon, 24 Aug 2026 19:12:05 +0200 Subject: [PATCH 3/6] Simplify repository convergence notes after consolidation --- docs/INTEGRATION_CONVERGENCE.md | 130 ++++++++++---------------------- 1 file changed, 38 insertions(+), 92 deletions(-) diff --git a/docs/INTEGRATION_CONVERGENCE.md b/docs/INTEGRATION_CONVERGENCE.md index 9afe58b6..fd354d03 100644 --- a/docs/INTEGRATION_CONVERGENCE.md +++ b/docs/INTEGRATION_CONVERGENCE.md @@ -1,113 +1,59 @@ -# Integration convergence plan +# Repository convergence and cleanup -This document defines a non-destructive path for converging the experimental product lines in this repository. +The repository has already converged onto `main`. Cleanup must preserve recoverability while removing redundant active branches and stale planning material. -## Safety rule +## Current source of truth -Do not delete, force-push, squash, or rewrite any source branch until the convergence branch is validated and the archived snapshots below have been checked. +- `main` — active product/development branch. +- `gh-pages` — generated deployment branch; keep while GitHub Pages depends on it. +- `agent-control` — operational branch used by the repository agent; keep while that workflow is in use. -Snapshot branches created on 2026-08-21: +The old integration branch `integration/convergence-2026-08` is no longer the intended development line. `main` contains the converged firmware, simulator/twin, browser configurator and lab panel. -- `archive/2026-08-21-main-baseline` — exact snapshot of `main` -- `archive/2026-08-21-sku-v1` — exact snapshot of `feature/sku-v1` -- `archive/2026-08-21-sim-twin-pyvista` — exact snapshot of `feature/sim-twin-pyvista` -- `archive/2026-08-21-configurator-v5` — exact snapshot of `feature/growbox-config-v4-docs` -- `archive/2026-08-21-pages-live` — exact snapshot of the currently deployed `gh-pages` -- `archive/pre-squash-history` — existing full history retained from before the v1 baseline squash +## Legacy UI that must be preserved -The working convergence branch is: +`tools/panel/` is the older Growbox ML laboratory dashboard / JSON scenario configurator. It is intentionally retained in `main`. -- `integration/convergence-2026-08` +The file `tools/panel/static/index.html` in `main` is byte-for-byte the same Git blob as in `feature/sim-twin-pyvista` (`76713f4aa1a43658313826acf713fd2037613343`). Deleting the redundant feature branch therefore does not remove this dashboard. -It starts from `feature/sim-twin-pyvista`, because that line already contains the `feature/sku-v1` history plus the later simulator, calibration, profile and PyVista twin work. +The newer React configurator remains under `web/`, including the v5 schema snapshot in `web/schema/environment-controller.v5.json`. -## Product lines to preserve +## Redundant feature branches -### Firmware / controller baseline +Each branch below has an exact archive snapshot and can be treated as redundant after this cleanup branch is reviewed: -Source: `main` +| Feature branch | Exact archive snapshot | +|---|---| +| `feature/sku-v1` | `archive/2026-08-21-sku-v1` | +| `feature/sim-twin-pyvista` | `archive/2026-08-21-sim-twin-pyvista` | +| `feature/growbox-config-v4-docs` | `archive/2026-08-21-configurator-v5` | -Preserve the ESP-IDF application, portable C++ controller, generated model runtime, deterministic safety supervisor, UART/NDJSON demo protocol, host tests, Python ML pipeline, board profiles and existing documentation. +The archive comparisons are identical at the commit level. -### Simulator / calibration / scientific twin +## Archive branches to keep for now -Source: `feature/sim-twin-pyvista` +- `archive/2026-08-21-main-baseline` +- `archive/2026-08-21-sku-v1` +- `archive/2026-08-21-sim-twin-pyvista` +- `archive/2026-08-21-configurator-v5` +- `archive/2026-08-21-pages-live` +- `archive/pre-squash-history` -Preserve calibration tools, deviations/foresight work, GrowboxProfile, PyVista scientific twin, scene/profile tests and related simulator documentation. +These are recovery points, not active development branches. They can be reconsidered later after the new architecture and ML contract stabilize. -### Hardware configurator / browser 3D chamber +## Contract state -Source: `feature/growbox-config-v4-docs` +Do not mix repository cleanup with the ML redesign: -This is a sparse frontend line and must NOT be merged wholesale because it intentionally removes firmware/product files. Preserve selectively: +- firmware/controller currently uses schema v4: 4 pots, 128 features, 15 outputs; +- browser tooling carries schema v5: up to 9 pots, 228 features, 25 outputs; +- the next ML architecture may replace this with smaller stateless contracts, but that is a separate product change. -- `web/**` -- the schema/configurator docs that are still relevant -- contract validation/gate tooling where useful -- deployment configuration only after replacing branch-specific assumptions +## Cleanup performed on `cleanup/repository-2026-08` -The browser frontend currently contains both the schema-driven JSON configurator and `/chamber-3d` React Three Fiber view. +- removed root `continue_test.md` — old machine/audit handoff notes; +- removed `docs/plan.md` — obsolete v2 planning document that conflicts with the current v4/v5 state; +- retained both `tools/panel/` and `web/`; +- reduced this document to the current repository state. -### Deployed Pages artifact - -Source: `gh-pages` - -Treat as generated output, not a source branch. Keep the 2026-08-21 archive snapshot until a replacement Pages pipeline from the converged source has been validated externally. - -## Known contract split - -Do not silently reconcile this during cleanup. - -- `main` firmware/controller line currently uses the v4 contract (4 pots, 128 features, 15 outputs). -- the configurator line has evolved to v5 (up to 9 pots, 228 features, 25 outputs), although some branch/file names and README text still say v4. - -This mismatch is architectural/product work, not repository cleanup. Keep both states recoverable and label them accurately until a deliberate migration is performed. - -## Current preservation inventory - -This table records what has already been carried into the convergence branch and what must remain recoverable before source branches can be removed. - -| Source / artifact | Status in convergence | Deletion disposition | -|---|---|---| -| `main` firmware/controller tree | Preserved because the twin line descends directly from the v1 baseline | Keep source until full validation; dated snapshot exists | -| `feature/sku-v1` | Fully contained in `feature/sim-twin-pyvista`, therefore also contained in convergence history | Candidate for deletion only after convergence is accepted; dated snapshot exists | -| `feature/sim-twin-pyvista` | Convergence branch is a direct descendant; no history was reconstructed or flattened | Candidate for deletion only after convergence is accepted; dated snapshot exists | -| `web/**` from configurator line | Imported into convergence without merging sparse-branch deletions | Source remains until final web/Pages validation; dated snapshot exists | -| configurator schema v5 | Preserved as `web/schema/environment-controller.v5.json` | Do not replace root firmware v4 schema until an explicit migration | -| configurator golden export | Preserved as `web/schema/examples/minimal-single-pot.v5.json` and used by web tests | Source copy may become redundant after validation; dated snapshot exists | -| current firmware schema v4 | Remains at `schemas/environment-controller.json` unchanged | Required until deliberate firmware contract migration | -| `docs/HARDWARE_CONFIGURATOR.md` on sparse branch | Historically useful design notes, but contains stale v4 assumptions | Preserve in `archive/2026-08-21-configurator-v5`; do not copy as current authority without rewriting | -| `docs/SCHEMA_V4_FIELD_GUIDE.md` on sparse branch | Legacy v4 field guide; conflicts with current web v5 dimensions | Preserve in archive as historical material; do not expose as current v5 documentation | -| `gate/check-contract.mjs` + tests | Valuable independent contract-validator logic, but mixed stale v4 names/comments with actual v5 checks and branch-specific root paths | Keep recoverable in archive; decide later whether to port cleanly under `web/` after CI convergence | -| branch-specific root `AGENTS.md` / root pnpm gate | Sparse-branch operating rules, not safe as monorepo root authority | Preserve in archive; selectively port only rules still valid for converged tree | -| configurator deployment workflow | Branch-specific publisher to `gh-pages` | Keep current deployment unchanged until candidate deployment is verified | -| `gh-pages` generated tree | Current externally verified live build | Keep live plus dated snapshot until replacement deployment is proven | - -A source feature branch may be deleted later even when historical notes remain only in a dated archive branch; the archive is deliberately the lossless recovery layer. The active tree should not be polluted with stale documentation merely to make a feature branch deletable. - -## Convergence order - -1. Keep all source branches and archive snapshots untouched. -2. Use `integration/convergence-2026-08` as the only convergence workspace. -3. Validate the simulator/twin line against its existing tests before importing frontend work. -4. Import the configurator frontend selectively; never merge its sparse branch as a whole. -5. Keep firmware v4 and frontend v5 boundaries explicit until a deliberate schema migration is designed. -6. Add/repair documentation and live-demo links only after the source layout is stable. -7. Build/test firmware, host C++, Python ML/simulator and frontend independently. -8. Deploy a candidate Pages build without deleting the current `gh-pages` history/snapshot. -9. Verify both `/` and `/chamber-3d` externally. -10. Only after all validation passes, decide which feature branches are redundant and may be deleted. Archive snapshots remain available until a later explicit cleanup decision. - -## Definition of done before deleting source branches - -- firmware build passes for intended ESP32-S3 profile(s) -- portable C++ host tests pass -- Python tests for ML/simulator/profile/twin pass -- frontend typecheck, lint, tests and production build pass -- JSON configurator imports/exports the intended schema correctly -- `/chamber-3d` works from the final Pages URL -- README describes the actual architecture and contract versions without stale feature/output counts -- every useful source-only artifact has an explicit disposition in the preservation inventory -- archive snapshots are confirmed present - -Until every relevant item above is true, no historical/product branch is considered disposable. +Historical copies of removed material remain recoverable from existing archive/history branches. From cbec21578da4048b7d8a7f0a4ebf631462641260 Mon Sep 17 00:00:00 2001 From: Michal Matuszewski <90936684+MichalMatu@users.noreply.github.com> Date: Mon, 24 Aug 2026 19:12:48 +0200 Subject: [PATCH 4/6] Remove obsolete repository branch guide --- docs/REPO.md | 53 ---------------------------------------------------- 1 file changed, 53 deletions(-) delete mode 100644 docs/REPO.md diff --git a/docs/REPO.md b/docs/REPO.md deleted file mode 100644 index 41e6bf6b..00000000 --- a/docs/REPO.md +++ /dev/null @@ -1,53 +0,0 @@ -# Repozytorium — gałęzie i porządek - -## Gałęzie - -| Gałąź | Rola | -|-------|------| -| **`main`** | **v1 baseline** — jeden commit, zamrożona baza kodu | -| **`feature/sku-v1`** | Praca nad wąskim SKU (stałe wejścia/wyjścia, bez konfiguracji sprzętu) | -| **`archive/pre-squash-history`** | Pełna stara historia git (168 commitów) — tylko archiwum | - -### Stan v1 baseline (świadome ograniczenia) - -Kod na `main` to **uniwersalny kontrakt** (128 cech, 15 wyjść, mix & match I/O w panelu). -Okazało się to **ślepą uliczką** dla skutecznego treningu ML i testów kombinatorycznych. -**Nie kasujemy kodu** — encoder, safety i panel zostają jako baza; produkt v1 dopracowujemy na -`feature/sku-v1` (zamrożony zestaw czujników i aktuatorów pod jeden growbox). - -Domyślna gałąź na GitHub: **`main`**. - -## Sync Mac + Raspberry Pi - -```bash -git checkout main -git pull -make setup # lub setup-dev -``` - -Jedna maszyna robi zmiany → `commit` → `push` → druga `pull`. Nie kopiuj `build/`, `.venv/`, `sdkconfig` między maszynami. - -## Co jest w git / czego nie commituj - -| W git | Lokalnie (`.gitignore`) | -|-------|-------------------------| -| Źródła, schema, wygenerowany model C w `lib/.../generated/` | `build/`, `logs/`, `datasets/` | -| `docs/CONFIG_MATRIX.csv`, testy | `.venv/`, `sdkconfig`, `*.keras` | -| `continue_test.md` — audyt na Pi | `build/audit/*.jsonl` (checkpointy) | - -## Narzędzia testowe (nie mylić) - -| Narzędzie | Gdzie | Po co | -|-----------|-------|-------| -| `run_config_matrix` | Host | 59 profili I/O, encoder + safety (bez inference ML) | -| `board_engine_audit --matrix-only` | Płytka | Te same 59 na ESP | -| `panel_endpoint_audit` | Płytka + panel | Sweepy behawioralne ML | -| `exhaustive_board_audit` | Płytka | Siatki wartości × previous (~460k case) | -| `validity_matrix_audit` | Płytka | 32k masek validity | -| `probe_simulator` | Host | Fizyka symulatora (kierunki) | - -Stary `io_ladder_audit.py` — eksperyment; nie jest w Makefile. Można usunąć w osobnym commicie. - -## Kontynuacja audytu exhaustive - -Zobacz [continue_test.md](../continue_test.md) w katalogu głównym repo. From a20881e02d18a7162906fb18b24b794598b3f209 Mon Sep 17 00:00:00 2001 From: Michal Matuszewski <90936684+MichalMatu@users.noreply.github.com> Date: Mon, 24 Aug 2026 19:13:17 +0200 Subject: [PATCH 5/6] Fix stale schema-check script path --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f3b2d4b3..7bf8f2c4 100644 --- a/Makefile +++ b/Makefile @@ -108,7 +108,7 @@ fmt: ensure-venv lint: check-fast schema-check: ensure-venv - bash scripts/check_schema_v3.sh + bash scripts/check_schema.sh schema: schema-check From 93abfdf5a5216ad8b520e424559002ed3922754a Mon Sep 17 00:00:00 2001 From: Michal Matuszewski <90936684+MichalMatu@users.noreply.github.com> Date: Mon, 24 Aug 2026 19:13:32 +0200 Subject: [PATCH 6/6] Record repository cleanup pass --- docs/INTEGRATION_CONVERGENCE.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/INTEGRATION_CONVERGENCE.md b/docs/INTEGRATION_CONVERGENCE.md index fd354d03..be4a81c2 100644 --- a/docs/INTEGRATION_CONVERGENCE.md +++ b/docs/INTEGRATION_CONVERGENCE.md @@ -53,6 +53,8 @@ Do not mix repository cleanup with the ML redesign: - removed root `continue_test.md` — old machine/audit handoff notes; - removed `docs/plan.md` — obsolete v2 planning document that conflicts with the current v4/v5 state; +- removed `docs/REPO.md` — obsolete branch guide describing `main` as the old v1 baseline; +- fixed `Makefile` so `schema-check` calls the existing `scripts/check_schema.sh` instead of missing `scripts/check_schema_v3.sh`; - retained both `tools/panel/` and `web/`; - reduced this document to the current repository state.