# 11. Kebabkiller Studio — ostateczna architektura (3 AI + deterministyczny rdzeń) **Status:** zatwierdzony kierunek (sesja #17, 2026-06-14) **Rola:** ŹRÓDŁO PRAWDY architektury. Wersja śledzona w repo (kopia planu Cursor `kebabkiller_studio_architektura_8bceddbd`). **Implementacja:** Plan Mode → kod dopiero po „OK, rób". Robimy fazami, A jako pierwsza. Plan oparty na audycie **kodu** (nie dokumentacji). Najpierw błędy logiczne potwierdzone w repo, potem docelowa architektura i fazy. Zasada nadrzędna: **separacja warstw twardą granicą kodu** — to lekarstwo na chaos. ## Wizja produktu (wchłonięta z docs/05, sesja planowania 2026-06-09) **Kebabkiller Studio** = fabryka serialu viralowych odcinków 9:16 (TikTok/Shorts/Reels). Twórca + Scenarzysta planują odcinek → jedna akceptacja → Reżyser produkcji generuje spójne klipy → montaż zewnętrzny. **Nie** generator jednej losowej sceny. **Przepływ:** Katalog (biblioteka assetów) → Plan odcinka (sceny, braki materiałów, preferencje) → [Akceptacja] → Reżyser produkcji (technika + render) → Klipy + manifest → Recenzja (poprawka jednej sceny = re-render jednego klipu). **Trzy elementy:** (1) Katalog główny — postacie, tła, rekwizyty; (2) Plan odcinka — sceny, braki do dostarczenia, preferencje; (3) Paczka produkcyjna — `E01_SC01.webm` + `E01_manifest.json`. Odcinek ~45 s = wiele klipów (2–10 s, max ~10 s / render GPU), 1 beat = 1 scena = 1 plik. **Mapowanie wizja → fazy implementacji (z docs/05 F1–F4 na Fazy A–F):** | docs/05 faza | Pokrycie w Fazach A–F | Status | |---|---|---| | F1 (Plan + Scenarzysta + katalog) | Faza A (PlanValidator, frozen plan, jeden kanał) | ✅ zrobione | | F0 (Silnik klipu I2V) | Faza B (determinizm) + Faza C (osie, Klatka Zero, GPU) | ✅ B done, C częściowo | | F2 (Reżyser pod plan → paczka) | Faza B (jeden builder) + Faza C (composite) + Faza D (Snapshot ciągłości) | ✅ B done, C/D częściowo | | F3 (Recenzja + re-render sceny) | Faza D (resume partial) | 🔲 do weryfikacji z GPU | | F4 (Projekt serialu / biblia) | Faza F (engine_profile, skórka per serial) | 🔲 do zrobienia | > **docs/05 pozostaje jako archiwum wizji produktu** (nie jest już źródłem prawdy — treść wchłonięta powyżej). ## Status faz - [x] Faza A (keystone) — jeden kanał zapisu scen + PlanValidator + frozen plan + sprzątnięcie wizarda/frontendu + legacy POST=410 + naprawa docs (sesja #18) - [x] Faza B — deterministyczny Reżyser: `ref_id` (@ID), jeden builder, stały seed z planu, produkcja = podgląd, golden test (sesja #19) - [ ] Faza C — Klatka Zero + rozbicie I2V_PRODUCTION + żywe tło + IP-Adapter _(częściowo: część bez GPU ZROBIONA — sesja #20; IP-Adapter + realny klip + AI-gen klatki ODŁOŻONE do lekkiego deploymentu RunComfy — patrz sekcja D)_ - [~] Faza D — Snapshot SSOT + picker klatki + resume partial _(częściowo: PR #17 (ekstrakcja + Picker) + PR #20–#22 (Snapshot/Take, fix resume/superseded, tenant-scope); e2e GPU do weryfikacji)_ - [x] Faza E — AI-Inżynier MVP (pętla naprawcza z cofaniem) — osobny moduł `/api/system-agent`, bramka tokenem, diagnoza read-only → propose → apply (checkpoint git + bramka testów + auto-rollback) → [Cofnij] + Dziennik Napraw + panel UI (sesja #21) - [ ] Faza F — Studio-lustro UI + sprzątanie martwego kodu **Ustalenie diagnostyczne 2026-06-15 (sesja #20) — UWAGA: to PROTEZA, nie docelowa architektura.** Zdiagnozowano przyczynę freeze: za mały VRAM (`AMPERE_24` 24 GB na Wan 14B). Łańcuch B+C zwalidowano e2e na GPU (zaakceptowany plan → `produce` → klip WEBM `output/export/.../*.webm`: kompilacja @ID → enrich żywego tła + style_tags → composite Klatki Zero → workflow RunComfy → WEBM + manifest). **ALE** zrobiono to stopgapem — podbiciem hardware **starego, ciężkiego deploymentu** (`AMPERE_24`→`AMPERE_48`, 2436 nodów + Manager, cold start ~7 min). To **sprzeczne z planem** ("zastępuj nie sklejaj" + `RUNCOMFY_DEPLOYMENT.md`: „nie reużywaj starego z Managerem"). **Docelowo (Faza C-GPU): NOWY lekki deployment ComfyUI-Minimal.** Faza C-GPU pozostaje NIEZAKOŃCZONA (IP-Adapter + ControlNet/depth + realny klip z zamkiem tożsamości — wciąż do zrobienia). Stan ubocznych zmian sesji #20: hardware starego deploymentu pozostawiony na `AMPERE_48`, harness `backend/scripts/seed-smoke.mjs` + placeholdery zostawione. Szczegóły: `docs/RUNCOMFY_DEPLOYMENT.md`. ## A. Błędy logiczne znalezione w kodzie (zweryfikowane) - ~~**Domino jest martwe.**~~ **NAPRAWIONE (PR #17 + #20–#22).** PR #17: ekstrakcja klatek (`frameExtractor.js`), Picker (`ContinuityPicker.jsx`), tabela `continuity_frames`. PR #20: antywzorzec „Domino” (zmienny `_last.jpg` między scenami) **zastąpiony** niemutowalnym **Snapshot SSOT** (`scene_snapshots`, `snapshotStore.freezeSnapshot`) + walidacja **Take** (`validateTakeAgainstSnapshot`). PR #21: fix superseded snapshot + resume po `plan_scene_id` (`resolveResumePoint`). PR #22: tenant-scope snapshotów (`tenantContext.js`, `DEFAULT_TENANT_ID='default'`). - **Brak determinizmu.** Seed = `Math.floor(Math.random()*...)` w [backend/src/video/runComfyEngine.js](../backend/src/video/runComfyEngine.js) (l.184) + LLM `temperature` 0.2-0.4 w [backend/src/ai/director.js](../backend/src/ai/director.js). Ten sam plan != ten sam klip. - **Podgląd != produkcja.** Tylko podgląd woła `buildDynamicWorkflowPayload` (wstrzykuje `style_tags` + anchor do promptu). Produkcja w [backend/src/video/productionQueue.js](../backend/src/video/productionQueue.js) używa `enrichDirectorJson`, który **nie** wstrzykuje stylu projektu do `positive_prompt`. Styl serialu nie trafia do GPU w renderze odcinka. - ~~**4 buildery promptu o różnej kolejności bloków.**~~ **NAPRAWIONE (Faza B).** Jeden builder `compileScenePlan`/`buildSceneDirectorPlan` w `productionDirector.js`. Legacy `director.js` poza torem renderu; `i2vProduction.js` usunięty. - **Brak stabilnych ID + zła postać.** Assety to losowe `uuid` ([backend/src/db/episodeModels.js](../backend/src/db/episodeModels.js)). `executeAssetBinding` bierze `context.characters?.[0]` (pierwsza postać z bazy), a produkcja nie przekazuje `projectId`/`episodeId` -> brak kontekstu serialu i ryzyko złej postaci. - **Desync composite.** `hasCompositeRefs` (legacy `reference_path`) w director.js vs `hasComposite` (episode refs) w productionDirector.js; `stripRedundantTextBlocks` wymaga obu assetów i dokładnego dopasowania stringa (parafraza LLM ucieka). - **Tło zamrożone.** `I2V_PRODUCTION` ([backend/src/video/wanConfig.js](../backend/src/video/wanConfig.js)) mrozi kadr przez denoise 0.85 + static + anchor; brak osobnego wektora animacji tła; override sceny nie cofa już wbitego `camera_motion`/anchor w prompcie. - **Brak IP-Adapter** w `wan_workflow_api.json` mimo deklaracji w system prompcie (tylko CLIPVision) — tożsamość słabo zablokowana. - **Trzy kanały zapisu scen / dwóch planistów:** Scenarzysta ([backend/src/ai/screenwriter.js](../backend/src/ai/screenwriter.js), bez UI), narzędzia Desk ([backend/src/ai/directorDesk/agentTools.js](../backend/src/ai/directorDesk/agentTools.js)), REST w [backend/src/api/routes.js](../backend/src/api/routes.js). - **Dwa systemy "odcinków":** `GET /projects/:id/episodes` -> `episode_plans`, `POST` ten sam path -> tabela `episodes` ([backend/src/api/routes.js](../backend/src/api/routes.js)). - **Martwe stany wizarda:** `setSceneAnchors`/`reorderScenes` dozwolone, ale bez implementacji; `canAdvance` dla ASSETS nie sprawdza przypisania assetu, choć `validateEpisodePlan` wymaga ([backend/src/ai/directorDesk/wizardStateMachine.js](../backend/src/ai/directorDesk/wizardStateMachine.js)). - ~~**Brak resume produkcji:**~~ **CZĘŚCIOWO NAPRAWIONE (PR #17 + #21).** `resumeProductionFromPartial` + `resolveResumePoint` po `plan_scene_id`; wymaga weryfikacji e2e z GPU. - **Duży martwy frontend:** brak `EpisodePlan.jsx`, osierocone `JobStatus.jsx`, `MobileSceneEditor.jsx`, cały `api.episodePlans` (poza raw `produce`). - ~~**AI-Inżynier nie istnieje** w kodzie.~~ **NAPRAWIONE (Faza E, sesja #21).** Moduł `backend/src/ai/systemAgent/` istnieje i działa. ## B. Docelowa architektura ```mermaid flowchart LR subgraph creative [Tor tworzenia] SC[Scenarzysta] --> PV[PlanValidator kod] PV --> ACC[Tworca akceptuje] ACC --> REZ[Rezyser produkcji deterministyczny] REZ --> KLIP[Klipy + manifest] end subgraph core [Rdzen KOD nie AI] BRAIN[StudioBrain per projekt] COMP["@ID compiler + staly seed"] SNAP[Snapshot SSOT] COST[Straznik Kosztow] end subgraph maint [Tor utrzymania] INZ[AI-Inzynier z cofaniem] end REZ -.-> COMP REZ -.-> SNAP INZ -.->|diagnoza read-only| KLIP INZ -.->|naprawa kodu git checkpoint| core ``` - **Scenarzysta** — fabula w granicach [docs/CAPABILITIES.md](CAPABILITIES.md); jedna implementacja, wolana z Director's Desk. Wynik: sceny/logline/braki. Nie dotyka GPU. - **Reżyser produkcji** — deterministyczny: jeden builder promptu z `@ID`, staly seed, ta sama logika w podglądzie i produkcji. Zero LLM w torze renderu. - **AI-Inżynier Studia** — osobny modul `/api/system-agent/*`, osobny prompt. Petla: zglaszasz problem -> diagnoza read-only -> propozycja diff -> wspolna zgoda -> checkpoint git -> apply + testy (auto-rollback gdy czerwone) -> reczne [Cofnij] + Dziennik Napraw. Poreze bezpieczenstwa: to **NIE drugi Rezyser** — edycje fabuly/scen odsyla do Scenarzysty; dostep tylko za **tokenem wlasciciela** (LAN/tunnel); zapis tylko do whitelisty plikow (**nigdy** `.env`, sekrety ani zlote pliki: `director.js`, `mockEngine.js`, `runComfyEngine.js`). - **Uwaga (anti-konflikt):** ten zakaz dotyczy **wylacznie autonomicznego AI-Inzyniera** (Faza E). Praca fazowa pod kontrola wlasciciela (Fazy B/C/D) **moze** edytowac `runComfyEngine.js` (seed, node IP-Adapter, last-frame) — pod review + zielonymi testami. „Zlote pliki" = nie kasowac / nie przepisywac hurtem, a nie „zamrozone na zawsze". - **Rdzeń (kod, nie AI):** `PlanValidator`, `@ID` compiler, Strażnik Kosztów, staly seed, Snapshot ciągłości, `buildProjectBrain` (istnieje), transakcyjny czat z undo (istnieje: `is_committed`/`undo_of_id`). ## C. Decyzje zamkniete - Jedyny kokpit: Director's Desk. Stary flow EpisodePlan + osierocone komponenty do usuniecia. - Postac = wycinek PNG z alfa (`@char`); podwojny zamek: composite + IP-Adapter. Tlo = `@loc`, geometria trzymana struktura (depth), tlo zyje promptem animacji. - **Green-screen na martwej plycie odrzucony** — stabilnosc osiagamy struktura (depth) + IP-Adapter, nie zamrazaniem tla. - Klatka Zero (scena 1) = osobny tani etap. **Pierwsza klatka to problem OBRAZU, nie wideo** — iterujesz tanio na statycznym obrazie, zanim ruszy drogie GPU. Cztery zrodla: (1) skladanie `@char + @loc` (domyslne, 0 zl), (2) upload gotowej klatki, (3) generowanie 1 obrazu AI, (4) klatka z biblioteki / poprzedniego odcinka. Sceny 2+ = zamrożony Snapshot z poprzedniej sceny + picker klatki. - **Pozycja/skala Klatki Zero = KASKADA (sesja #20):** rozwiazywanie `override sceny → domyslna na assecie (@char) → fallback (hardcoded)`. NIE scena-only (retrofit dop. w Fazie F), NIE asset-only (zabija rezyserie ujec). Storage (czysta karta, bez backfillu): override sceny w `plan_scenes.ai_overrides_json.composite`; domyslna assetu w nowej nullable kolumnie `assets.composite_default_json`. Resolwer `resolveCompositeConfig` ([backend/src/video/compositeStartFrame.js](../backend/src/video/compositeStartFrame.js)). W Fazie C tylko model danych + resolwer dla composite — NIE cala kaskada UI `engine_profile` (to Faza F). - Koszty ku zeru: mock/obraz najpierw, GPU po akceptacji. **LLM local-first** — router intencji i rozmowa na lokalnym modelu (Ollama/llama.cpp), chmura tylko jako fallback / heavy "rozpisz pomysl". - gema-0: poza architektura (zero zaleznosci). - **Czysta karta — brak migracji danych historycznych.** Stare projekty nie sa potrzebne. Baza SQLite (`backend/data/studio.db`) moze byc w kazdej chwili skasowana i odtworzona przez seed (`init.js`). Migracje schematu (np. kolumna `ref_id` w Fazie B) **nie musza robic backfillu** — zakladaja czysty stan. - **ZASADA NADRZEDNA: „Zastepuj, nie sklejaj".** Stary kod byl pokrecony i niespojny. Gdy legacy jest niespojny — buduj JEDNA czysta implementacje i **usun stara**; **nie** zostawiaj zlych rozwiazan jako fallback, nie godz kilku zlych pomyslow w hybryde („potwora"). Granica: trzymaj sie zakresu biezacej fazy (nie rozlewaj sie na kolejne). - **Kontrakt @ID (zamkniety):** w `assets` dodajemy **tylko** kolumne `ref_id` (stabilny, **niemutowalny** slug, np. `char_kebabkiller`, bez `@`). Namespace (`char/loc/prop/detail`) **wyprowadzamy z istniejacego `type`** — NIE dodajemy redundantnej kolumny `kind`. `@` dokleja kompilator promptu przy budowie. Zmiana nazwy wyswietlanej NIE zmienia `ref_id`. - **Pozycja/skala Klatki Zero = KASKADA (zamkniete):** rozwiazywanie `override sceny -> domyslna na assecie (@char) -> fallback (obecny hardcoded)`. NIE scena-only (retrofit w Fazie F) ani asset-only (zabija rezyserie ujec). To **ten sam wzorzec kaskady co `engine_profile` w Fazie F** — wybor teraz = zero przerobek pozniej. W Fazie C robimy tylko model danych + resolwer dla composite (NIE cala kaskade UI Fazy F). ## D. Fazy (z kryterium "done") - **Faza A (keystone, pierwsza):** jeden planista + twardy `PlanValidator` (kod) jako granica Scenarzysta->Reżyser + frozen plan; usuniecie duplikacji i martwego frontendu; **naprawa mylacych docs** (`HANDOFF_AKTUALNY.md`, `03_AGENT_STATE_AND_TASKS.md`) tak, by kazda nowa sesja startowala z prawdy (UI = Director's Desk; EpisodePlan = legacy; zrodlo prawdy = ten dokument). Done: plan poza limitami odrzucony przez kod; jeden kanal zapisu scen; docs startowe zgodne z kodem. - **Faza B (ZREALIZOWANA, sesja #19):** deterministyczny Reżyser — `@ID` compiler (kolumna `ref_id` w assetach, namespace z `type`, BEZ `kind`), jeden builder, staly seed, produkcja uzywa tej samej logiki co podglad (koniec preview != prod), wstrzykniecie `style_tags`/anchor. Done: 2x ten sam plan = ten sam payload. - **Realne zmiany:** (1) `assets.ref_id` — stabilny, niemutowalny slug `type+name` (np. `char_kebabkiller`, bez `@`); migracja BEZ backfillu (`init.js`+`schema.sql`); namespace wyprowadzany z `type`. (2) JEDEN deterministyczny builder `compileScenePlan`/`buildSceneDirectorPlan` (`productionDirector.js`) — `expandScenePrompt` (LLM) **usuniety** z toru renderu; stara `compileDeterministicScenePlan`/`enrichProductionPlan`/`stripRedundantTextBlocks` zastapione; legacy `director.js` (poza torem renderu) nietkniety; `i2vProduction.js` usuniety. (3) `deterministicSeed(planId:sceneId)` (`wanConfig.js`) — `Math.random()` usuniety z `runComfyEngine.js`. (4) wspolny `enrichDirectorForRender` (`workflowBuilder.js`) wolany przez podglad i produkcje; rozjechany `enrichDirectorJson` (`productionQueue.js`) zastapiony. (5) **Strażnik:** `productionPayloadGolden.test.js`. Testy: 92 → 110 pass. - **Faza C:** Klatka Zero (compose cutout+tlo, pozycja z panelu) + rozbicie `I2V_PRODUCTION` (kamera / animacja tla / beats) + zywe tlo + node IP-Adapter. Done: podglad kolazu 0 zl; 1 klip z zywym tlem i stala geometria. - **Faza C — zrobione (bez GPU), sesja #20:** podzielono fazę na czesc 0 zl / niezalezna od GPU (zrobiona) i czesc GPU (odlozona — patrz nizej). Zrealizowane: 1. **Rozbicie `I2V_PROFILES` na niezalezne osie** kamera / tlo / beats ([backend/src/video/wanConfig.js](../backend/src/video/wanConfig.js)) — `camera.static` NIE zamraza juz tla; usuniety zlepek `staticCamera`/`singleBeat` ("zastepuj nie sklejaj"). 2. **Zywe tlo odpiete od kamery** — `LIVING_BACKGROUND_PROMPT` (dym/ogien/neony, geometria stala) wstrzykiwany niezaleznie od `static_camera`, sterowalny override `background_motion=frozen` ([backend/src/ai/directorDesk/workflowBuilder.js](../backend/src/ai/directorDesk/workflowBuilder.js); `i2vProduction.js` usuniety — logika przeniesiona do `workflowBuilder.js`). Anchor "feet on ground" = uziemienie POSTACI, zostaje. 3. **Klatka Zero — kaskada composite** (`scene → asset → fallback`): `assets.composite_default_json` (model + resolwer + pozycja/skala sterowalne), endpoint **podgladu kolazu 0 zl** `POST /composite/preview` (zero GPU), panel UI (suwaki pozycja/skala/zrodlo, live preview). - **Strażnik:** golden `productionPayloadGolden` zielony (swiadoma aktualizacja — node 55 niesie teraz "Living background"); `runComfyEngine.js` NIETKNIETY. Testy: 110 → 115 pass. - **Faza C — ODŁOŻONE (GPU, bloker z sekcji F):** czeka na lekki deployment RunComfy. - **node IP-Adapter** w `wan_workflow_api.json` (drugi zamek tozsamosci) + edycja toru renderu wpinajaca composite/osie do realnego workflow. - **realny render klipu** z zywym tlem i stala geometria (1 klip = kryterium "done" calej Fazy C). - **zrodlo (3) Klatki Zero: generowanie 1 obrazu AI** (pozostale zrodla compose/upload/biblioteka — zrobione). - **Faza D (CZĘŚCIOWO ZREALIZOWANA, PR #17 + #20–#22):** Snapshot SSOT (zamiast Domino) + picker klatki + resume partial. Done: odcinek 3 scen = 3 spójne klipy + manifest, retry tylko brakującej sceny. - **Realne zmiany (PR #17):** (1) `frameExtractor.js` — ekstrakcja klatki końcowej + N kandydatów z klipu (ffmpeg). (2) `ContinuityPicker.jsx` — Picker kadru kontynuacji w UI. (3) tabela `continuity_frames` + API endpointy ciągłości. (4) `continuityEngine.test.js`. - **Realne zmiany (PR #20):** (1) `scene_snapshots` — append-only, wersjonowana, content-addressed (`sha256`). (2) `snapshotStore.freezeSnapshot` — kopiuje klatkę do niemutowalnego pliku. (3) `productionQueue.js` — promocja last frame → Snapshot sceny N+1; Take (`production_clips`) walidowany przez `validateTakeAgainstSnapshot`. (4) manual `start_frame_path` → snapshot `source=manual`. (5) `SNAPSHOT_CONTINUITY_AUDIT.md`. - **Realne zmiany (PR #21):** fix superseded snapshot (pobieranie najnowszego dla sceny); `resolveResumePoint` po `plan_scene_id` zamiast indeksu tablicy clips. - **Realne zmiany (PR #22):** tenant-scope (`storage/tenants/{tenant_id}/...`), `tenantContext.js`, guard `checkTenantScope.mjs`. Single-tenant: `DEFAULT_TENANT_ID='default'`. - **Nietknięte:** render-path determinizm (strażnik B zielony). **Pozostaje do weryfikacji:** pełny smoke e2e (3 sceny + resume partial) — wymaga GPU. - **Faza E (ZREALIZOWANA, sesja #21):** AI-Inżynier MVP — `/api/system-agent`, petla naprawcza z checkpointami git + bramka testow + Dziennik Napraw + [Cofnij]. Done: sztuczny blad -> trafna diagnoza + diff + zastosowanie z mozliwoscia cofniecia. - **Realne zmiany:** osobny modul `backend/src/ai/systemAgent/` (nie dotyka render-path B/C/D): `config.js` (bramka tokenem `SYSTEM_AGENT_TOKEN`, brak tokena = wylaczony), `pathGuard.js` (deny-by-default; blok `.env`/sekretow/zlotych plikow `director.js`+`mockEngine.js`+`runComfyEngine.js`/gema-0/Scenarzysty; whitelista `backend/src`+`frontend/src`; osobne poreze odczytu vs zapisu), `engine.js` (diagnose read-only → proposeRepair[before+diff, bez zapisu] → applyRepair[checkpoint git + bramka testow → commit | auto-rollback] → undoRepair[Cofnij]), `gitOps.js` + `testRunner.js` (iniektowalne), `repairJournal.js` + tabela `system_agent_repairs` (Dziennik, bez backfillu). Router `/api/system-agent/*` za tokenem (health publiczny). Frontend: `pages/SystemAgent.jsx` + zakladka „AI-Inżynier" + `api.systemAgent` (token w localStorage). **Render-path NIETKNIETY** — strażnik B/C/D zielony. Testy: 115 → 133 pass; `vite build` OK. - **Faza F:** Studio-lustro UI — `engine_profile` w panelu (kaskada Studio/Serial/Odcinek/Scena z rodowodem wartosci), skorka per serial; sprzatniecie osieroconego kodu. ### Prace Devina (PR #13–#16, po sesji #21) — cross-cutting, niezależne od faz - **PR #13 — refactor: shared utilities.** Wyekstrahowano `backend/src/utils/`: `llm.js` (wspólny wrapper wywołań LLM), `json.js` (safe JSON parse), `async.js` (sleep), `prompt.js` (dedup promptu). Zrefaktoryzowano `director.js`, `agentServer.js`, `intentRouter.js`, `memoryCompaction.js`, `screenwriter.js` (uwaga: `i2vProduction.js` refaktoryzowany w tym PR, potem usunięty). - **PR #14 — security hardening.** Helmet, rate limiting, path traversal protection, upload MIME validation. CORS middleware przed rate limiter (429 z headerami CORS). Zmiany w `index.js` i `routes.js`. - **PR #15 — unit tests coverage.** Nowe testy: `assetMetadata`, `falEngine`, `gitOps`, `jsonUtils`, `mockEngine`, `screenwriter`, `storyboardMock`, `systemAgentRouter`, `testRunner`. Testy: 133 → **227 total** (226 pass, 1 naprawiony w audycie 2026-06-21). - **PR #16 — error handling.** Propagacja błędów zamiast cichego połykania w `routes.js`, `systemAgent/engine.js`, `episodeModels.js`. ### Prace Devina (PR #20–#22, 2026-06-26) — ciągłość / snapshot - **PR #20 — Snapshot SSOT + Take validation.** Zastępuje antywzorzec Domino. `scene_snapshots`, `snapshotStore.js`, `snapshotModels.js`, zmiany w `productionQueue.js`. Audyt: `SNAPSHOT_CONTINUITY_AUDIT.md`. - **PR #21 — fixy ciągłości.** Superseded snapshot (pobieranie latest); resume po `plan_scene_id` (`resolveResumePoint`). Testy: `snapshotValidation.test.js`, `resumeResolvePoint.test.js`. - **PR #22 — tenant-scoped snapshots.** `tenantContext.js`, ścieżka `storage/tenants/{tenant_id}/...`, `checkTenantScope.mjs` w pretest. Testy: 227 → **237 pass**. ## E. Rekomendacja "co robimy jako pierwsze" **Faza A.** Pure-code, zero LLM, zero GPU, w pelni odwracalne; usuwa zywe zrodlo chaosu (dwoch planistow + trzy kanaly zapisu) i stawia zwornik (`PlanValidator`), bez ktorego deterministyczny Reżyser nie ma czystego wejscia. Najtanszy ruch o najwiekszej dzwigni. ## F. Ryzyka - Jeden przebieg I2V (Faza C) wymaga wezlow ControlNet/depth + IP-Adapter na GPU. **Bloker = brak lekkiego deploymentu** (stary jest za ciezki: 2436 nodow + Manager). Diagnoza sesji #20: freeze byl od VRAM (24 GB za malo) — potwierdzone, ale "naprawione" PROTEZA (podbicie hardware starego). Docelowo wg planu: NOWY lekki deployment ComfyUI-Minimal (`RUNCOMFY_DEPLOYMENT.md`: „nie reuzywaj starego z Managerem"). Faza C-GPU NIEZAKONCZONA. - AI-Inżynier z prawem zapisu (Faza E) — bramka testow + checkpoint git obowiazkowe; zapis tylko do whitelisty (nigdy `.env` ani zlote pliki). ## G. Uwaga dla nowej sesji (anti-pokrecenie) Dokumentacja w `docs/` ma **wiele sprzecznych wersji** — NIE traktuj calego `docs/` jako zrodla prawdy. Zrodlo prawdy = **TEN dokument + realny kod**. **Dokumenty oznaczone LEGACY (nie ufaj, nie implementuj):** - `docs/01_PROJECT_VISION.md` — skrót wizji, tabela statusów nieaktualna - `docs/02_ARCHITECTURE.md` — stara architektura (Groq, green-screen), sprzeczna z docs/11 - `docs/04_AI_DIRECTOR_KNOWLEDGE.md` — stary model Reżysera, fazy 4.x, nie istniejące - `docs/06_INSTRUKCJA_OBSLUGI_V2.md` — opisuje UI które nie istnieje (przeniesiony do `docs/archive/`) - `docs/10_OPUS_VISION_BRIEFING.md` — jednorazowy briefing dla sesji Cursor **Archiwum wizji (nie źródło prawdy):** - `docs/05_EPISODE_PIPELINE.md` — wizja produktu wchłonięta do sekcji "Wizja produktu" powyżej **Odrzucone kierunki:** Programista/`07_DEV_AGENT_PLAN.md`, Cursor Cloud Agents API jako tor naprawy, PR #9 (Groq /dev) jako drugi Rezyser, Cursor w iframe, gema-0 merge. **Usunięte pliki (referencje historyczne):** - `backend/src/ai/i2vProduction.js` — usunięty; logika przeniesiona do `workflowBuilder.js` + `wanConfig.js` ## H. Protokół kontynuacji (anti-konflikt) Fazy B→C→D dzielą te same pliki na torze renderu, więc nie są niezależne. Żeby nie powstały rozbieżności: **Mapa nakładania plików (strefy zapalne):** | Plik | B | C | D | F | |---|---|---|---|---| | `backend/src/video/runComfyEngine.js` | seed | node IP-Adapter | last-frame | — | | `backend/src/video/productionQueue.js` | styl, preview=prod | — | resume + Snapshot/Take | — | | `backend/src/ai/directorDesk/workflowBuilder.js` | @ID compiler | osie I2V | — | — | | `backend/src/video/wanConfig.js` | — | rozbicie profilu | — | engine_profile | | `backend/src/db/episodeModels.js` | kolumna `ref_id` (bez `kind`) | — | — | — | `runComfyEngine.js` to główny punkt zapalny B/C/D. **Zasady (obowiązkowe):** 1. **Ściśle sekwencyjnie B → C → D.** Nigdy dwie z tych faz równolegle (wspólny `runComfyEngine.js` / `productionQueue.js`). E = osobny moduł, można niezależnie. F na końcu. 2. **Jedno okno / jedna gałąź na fazę.** Start fazy = `git pull`; koniec = merge do `main` **przed** następną fazą. Zero dwóch agentów równolegle na render-path. 3. **Kontrakty zamrożone:** schemat `PlanValidator` (A) i schemat `@ID` (B) to umowy. Zmiana kontraktu = kontrakt **+ wszyscy konsumenci w jednym commicie**, nigdy po cichu. 4. **`docs/11` to umowa, nie notatnik:** każda faza w **tym samym commicie** odhacza status i dopisuje realne zmiany projektowe. Kod rozjechany z `docs/11` → najpierw poprawiamy `docs/11`. 5. **Test determinizmu z B = strażnik B/C/D:** „2× ten sam plan = ten sam payload" musi zostać zielony po C i D. 6. **Commit per krok** — drobne, odwracalne.