# API aplikacji kart Wspólna aplikacja Fastify wystawia stan dowolnej karty, nawigację UML, checkpointy oraz Neovim wybrany przez MCP. Domyślny adres lokalnej instancji to `http://127.0.0.1:8080`. Kontrakt nie zależy od serii ani konkretnej karty; dane i recepty pochodzą z jej `card_source.json`. API nie zarządza cyklem życia kontenera i nie podpina pane tmuxa. Za operacje `start/reset/refresh/attach/detach` odpowiada `stemctl session`. API korzysta z kontenera wskazanego przez bieżący wybór MCP i steruje zawartością jego sesji: Neovimem, Termdebugiem/GDB i checkpointami maszyny. ## Tożsamość i stan | Metoda i endpoint | Znaczenie | | --- | --- | | `GET /api/identity` | `id`, UUID, wersja i SHA-256 źródłowego JSON-a karty. | | `GET /api/card-revision` | Rewizja plików używana do automatycznego odświeżania strony. | | `GET /api/state` | Złożony stan nawigacji, widoku, checkpointu i dostępności Neovima. | | `GET /api/control/state` | Lekki stan synchronizacji strony z klientem sterującym. | Serwer jest przeznaczony do pracy lokalnej. Nie ma warstwy uwierzytelnienia, dlatego nie należy wystawiać go bezpośrednio poza zaufany host. ## Nawigacja UML Hierarchia nawigacji jest stała: ```text card → task → block → phase → step → snapshot ``` Ruch kursora przez `move` lub `PUT current` nie uruchamia symulatora. Jawna aktywacja odbywa się przez `Enter` w WWW albo `F2` w WWW/Neovimie, które wywołują `POST /api/navigation/sync`. Dla poziomu BLOCK backend wybiera pierwszy STEP tego bloku. CARD i TASK są odrzucane, ponieważ nie wskazują konkretnego checkpointu diagramu. | Metoda i endpoint | Znaczenie | | --- | --- | | `GET /api/keyboard` | Skróty i obsługiwane poziomy nawigacji. | | `GET /api/navigation/catalog` | Wszystkie prawidłowe pozycje i ich indeksy. | | `GET /api/navigation/current` | Bieżąca pozycja oraz status checkpointu. | | `PUT /api/navigation/current` | Ustawia dokładną pozycję i poziom fokusu. | | `POST /api/navigation/move` | Przesuwa kursor o `delta` na wybranym poziomie. | | `POST /api/navigation/sync` | Odtwarza checkpoint przypisany do bieżącej, zapisanej pozycji. | Przykład ustawienia kroku — identyfikatory są danymi konkretnej karty: ```json { "task_id": "", "block_id": "", "phase_id": "", "step_id": "", "snapshot_ref": "", "focus_level": "step", "sync_requested": true, "actor": "stemctl" } ``` ## Checkpointy | Metoda i endpoint | Znaczenie | | --- | --- | | `GET /api/checkpoint/status` | Aktywna operacja, ostatni wynik i generacja. | | `POST /api/checkpoint/activate` | Odtwarza stan GDB przypisany do snapshotu. | Wywołanie orkiestratora przypina zarówno kontener, jak i rewizję karty: ```json { "snapshot_ref": "", "generation": 1784280000000, "expected_binding": { "container_id": "", "instance": "", "profile": "hazard3-sim", "target": "hazard3-baremetal" }, "expected_identity": { "id": "", "uuid": "", "version": "", "source_sha256": "" } } ``` Backend przechowuje bieżącą nawigację i stan viewera w SQLite. Domyślna baza to `.stem/card-state.sqlite3`; ścieżkę można zmienić przez `CARD_STATE_DATABASE`. Ta sama aplikacja wystawia HTTP również przez lokalny socket `.stem/card-api.sock` (`CARD_API_SOCKET`). Repozytorium jest montowane w kontenerze jako `/workspace`, dlatego Neovim wywołuje API przez `/workspace/.stem/card-api.sock` bez otwierania dodatkowego portu sieciowego. Replay kończy się powodzeniem wyłącznie ze statusem `ready`. Zmiana kontenera, socketu MCP albo źródłowego JSON-a podczas operacji powoduje odrzucenie wyniku; pozycja strony i `SYNC ON` nie są wtedy publikowane. ## Widok i Neovim | Metoda i endpoint | Znaczenie | | --- | --- | | `GET/PUT /api/viewer/state` | Skala, scroll oraz `visible/sync/control/expanded/fit`. | | `GET /api/nvim/state` | Bieżący bufor, okno, kursor i tryb Neovima. | | `PUT /api/nvim/cursor` | Ustawia `row`, `column` i opcjonalnie `window`. | | `POST /api/nvim/input` | Przekazuje do 256 znaków przez `nvim_input`. | | `POST /api/nvim/reset` | Resetuje cel i odświeża debugger (`F1`). | | `POST /api/nvim/redraw` | Dopasowuje host pane i grid UI, a następnie wykonuje pełny redraw (`Ctrl+\``). | | `WS /api/nvim-ui` | Strumień zewnętrznego UI Neovima do panelu WWW. | Pole `viewer.scroll` zapisuje położenie dokumentu (`x`, `y`), numer strony `page_index` oraz `sheet_scroll_top` dla jej wewnętrznego obszaru. Dzięki temu sterowanie API odtwarza ten sam fragment diagramu także wtedy, gdy przy dużym powiększeniu przewija się najpierw zawartość strony, a dopiero potem dokument. Wyłączenie `viewer.nvim.sync` automatycznie wyłącza również `viewer.nvim.control`. Samo ponowne włączenie synchronizacji nie uzbraja sterowania klawiaturą bez jawnego `control: true`. `viewer.allocator.visible` przechowuje stan przypiętego modelu alokatora. Model jest przełączany przez `Alt+6` i pokazuje fazę/krok, `allocp`, zajętość areny oraz wartości związane z bieżącym checkpointem. ### Podział odpowiedzialności widoków Interaktywny diagram UML pokazuje przepływ i służy do wyboru kroku. Nie renderuje pod SVG osobnych paneli kodu, terminala, rejestrów, pamięci ani ramki stosu. Te dane prezentuje `Nvim view`, ustawiany przez snapshot wybranego kroku. Snapshoty pozostają w JSON/API, mimo że nie są powielane wizualnie pod diagramem. ## Postęp zajęć i raport | Metoda i endpoint | Znaczenie | | --- | --- | | `GET /api/progress` | Katalog, statusy i podsumowanie wykonania. | | `PUT /api/progress/:itemId` | Ustawia `pending` albo `approved`, notatkę i aktora. | | `GET /api/report/teams.md` | Generuje bieżący raport Markdown do Teams. | | `GET/POST /api/events` | Odczytuje lub dopisuje chronologiczne zdarzenia z timestampem backendu. | | `POST /api/evidence` | Zapisuje PNG/JPEG i przypina go do zdarzenia. | | `GET /api/evidence/:name` | Udostępnia zapisany dowód. | | `GET /api/report/lesson.html` | Renderuje chronologiczny raport HTML z dowodami. | Zdarzenia są dopisywane do SQLite i obejmują nawigację, aktywacje checkpointów, reset/redraw Neovima, zmiany viewera oraz postęp. Dzięki temu raport pokazuje rzeczywistą kolejność pracy, a nie wyłącznie końcowy stan. ## Planowane strategie i adnotacje Strategie debugowania będą przypinane do pełnego klucza `task/block/phase/step/snapshot`. Adnotacja pozostanie osobnym rekordem: ```text strategy: id, label, commands, expected_observations annotation: id, strategy_id, target, geometry, style, text, visible ``` Planowane operacje `show/hide/toggle` zmienią wyłącznie `visible`. `add/remove` będą osobnymi, audytowalnymi operacjami. Dzięki temu ukrycie warstwy objaśnień nie usuwa przygotowanych oznaczeń.