docs: define host workspace and MCP access

This commit is contained in:
user
2026-07-17 08:25:07 +02:00
parent 1e1c124c9f
commit 1d8f16303e
4 changed files with 231 additions and 0 deletions
+89
View File
@@ -17,6 +17,10 @@ mieć wgląd w tę samą sesję, w której pracuje uczeń:
Dzięki temu agent widzi środowisko debugowania, a nie tylko statyczne pliki.
Punkt wejścia `stemctl` jest także projektem hostowym: pierwszy klon znajduje
się w `~/dev/workspace/stem/tools/stem-launcher`. Agent ani użytkownik nie
klonują launchera, kart lub repozytoriów odpowiedzi do kontenera.
## Aktualny fundament
`rv32i-hazard3-student-env` dostarcza źródła wspólnego modelu:
@@ -108,6 +112,91 @@ Aktualny ID uniemożliwia użycie socketu pozostałego po odtworzeniu kontenera.
`stemctl` traktuje te pliki jako szczegóły implementacyjne. Użytkownik i agent
dostają komendy wyższego poziomu.
### Kto tworzy sockety
Hostowy launcher `stem` najpierw tworzy katalog runtime i przekazuje go
Podmanowi jako bind-mount pod **tą samą bezwzględną ścieżką**. Po uruchomieniu
interfejsu debuggera procesy wewnątrz kontenera tworzą sockety:
- `tmux` tworzy `t.sock`,
- `nvim` tworzy `n.sock`.
Nie są one kopiowane ani przekazywane przez sieć: host i kontener widzą ten sam
plik Unix socket w zamontowanym katalogu. ID kontenera jest częścią ścieżki,
więc nowy kontener po `rm/start` dostaje nowy katalog i nie może przypadkiem
obsłużyć socketu poprzednika.
### Dynamiczny wybór kontenera
Stały provider MCP na hoście używa dwóch krótkich ścieżek:
```text
$XDG_RUNTIME_DIR/stem/mcp-selected/current/n.sock
$XDG_RUNTIME_DIR/stem/mcp-selected/current/t.sock
```
Polecenie `stemctl mcp select INSTANCE_OR_CONTAINER_ID` weryfikuje registry,
pełny ID i label kontenera oraz oba żywe serwery. Następnie atomowo przełącza
symlink `current` dla obu socketów. Dzięki temu kolejna operacja MCP trafia do
wybranej sesji tmuxa i Neovima bez restartowania Codexa. `stemctl mcp list`
pokazuje tylko rekordy registry, a `stemctl mcp status` potwierdza bieżący
wybór.
Wybór pozostaje jawny: samo stworzenie kontenera tworzy jego katalog socketów,
ale nie przejmuje automatycznie aktywnego MCP innej sesji.
### Wiele kont użytkowników i pomoc nauczyciela
Sockety muszą pozostać prywatne dla unixowego konta, które uruchamia
kontener, np.:
```text
/run/user/<uid-ucznia>/stem/<thread>/<instance>/<container-id>/
```
Nie montujemy ich do wspólnego `/tmp`, nie zmieniamy grup socketów tmuxa i nie
udostępniamy ich przez port sieciowy. Codex nauczyciela łączy się przez SSH na
konkretne konto ucznia; po drugiej stronie ograniczony wrapper MCP łączy się
lokalnie z jego `n.sock` i `t.sock`. Stdio SSH jest transportem MCP — socket
Unix nie opuszcza komputera ucznia.
Każdy uczeń ma własny tmux i Neovim. Można uruchomić wiele serwerów MCP dla
tej samej sesji (np. ucznia i nauczyciela), ale oba mogą równocześnie edytować
bufor lub wysyłać klawisze, więc nie ma gwarancji arbitrażu zmian.
Dostęp nauczyciela rozdzielamy na dwa klucze SSH:
- zwykły klucz nauczycielski z pełną powłoką, używany wyłącznie do świadomej,
ręcznej interwencji na koncie ucznia;
- osobny klucz automatyzacji Codexa z forced command, bez TTY, forwardingu i
powłoki, ograniczony do `nvim`, `tmux`, `status` i dozwolonych kontenerów.
Pełny klucz nauczyciela nie trafia do kontenera ani do konfiguracji MCP.
### Poziomy uprawnień MCP
Każdy wpis MCP otrzymuje jawny poziom dostępu. Poziom jest własnością klucza
SSH i wrappera po stronie konta ucznia, a nie ustawieniem przekazywanym przez
model lub klienta MCP:
| Poziom | Przeznaczenie | Dozwolone działania |
| --- | --- | --- |
| `observe` | podgląd postępów | stan nvim, lista i capture pane’ów tmuxa, logi i metadane; bez edycji i wysyłania klawiszy |
| `assist` | wspólne rozwiązywanie problemu | działania debuggera i jawnie dozwolona edycja/panele; bez ogólnego terminala oraz bez poleceń powłoki |
| `full` | interwencja nauczyciela | pełne sterowanie nvimem i tmuxem, w tym terminalem w wybranym kontenerze, jako konto ucznia |
`full` jest równoważny interaktywnej pracy na koncie ucznia w granicach
wybranego kontenera. W szczególności arbitralne `nvim-remote-expr`, `nvim-ex`
lub wysyłanie poleceń do panea tmuxa mogą uruchomić kod. Taki wpis tworzymy
wyłącznie dla nauczyciela i zapisujemy w audycie konto, instancję, container ID,
czas oraz użyty poziom.
Nie wystarczy przekazać `MCP_ACCESS_LEVEL=observe` do tego samego pełnego
serwera: niższe poziomy wymagają osobnych providerów z allowlistą narzędzi.
W przeciwnym razie użytkownik nadal mógłby użyć ogólnego Ex/Vimscriptu albo
terminala do obejścia ograniczenia. Klucz `full` może korzystać z obecnego
providera STEM, ponieważ jego możliwości są celowo pełne.
## Role profili
Profil `hazard3-sim`:
+50
View File
@@ -195,6 +195,29 @@ re-enumeracji. Nie przekazuje całego `/dev`. Build i test offline nie wymagają
artefaktu. Bez niego odmawia wykonania, chyba że użytkownik jawnie zaakceptuje
istniejący firmware. Zapobiega to testowaniu starego programu.
## Źródła projektu
Źródła kart i projektów pobiera wyłącznie `stemctl` na hoście, zawsze pod
`~/dev/workspace` danego konta Unix. Kanoniczny workspace STEM ma postać
`~/dev/workspace/stem`; nie używamy do pracy katalogów kontenera ani
przypadkowych klonów poza `~/dev/workspace`. Pierwszy klon launchera trafia do
`~/dev/workspace/stem/tools/stem-launcher` i od niego zaczyna się cały
bootstrap workspace. Typowy przepływ to:
```bash
stemctl workspace sync
stemctl series cards fetch inf pointers
stemctl debug rp2350 inf pointers 4
```
Katalog karty pozostaje na hoście, na przykład
`~/dev/workspace/stem/series/inf/pointers/`, i jest przekazywany kontenerowi
jako bind-mount `/workspace`. Nie klonujemy repozytoriów źródłowych wewnątrz
kontenera: kontenery są odtwarzalne i mogą zostać usunięte, natomiast host
zachowuje Git, zmiany ucznia, odpowiedzi i historię pracy. W obrazie lub
osobnym cache volume mogą znajdować się wyłącznie narzędzia, zależności i
odtwarzalne cache budowania.
## Instancje i sockety MCP
Stabilna nazwa logiczna:
@@ -227,6 +250,33 @@ Publiczne wejścia launchera to `stemctl mcp tmux INSTANCE` oraz
zweryfikowanego kontenera. Neovim MCP publikuje również stan i komendy
Termdebug/nvim-dap.
Dla jednego stale działającego klienta hostowego dostępny jest również jawny,
atomowy przełącznik obu socketów:
```bash
stemctl mcp list
stemctl mcp select INSTANCE_OR_CONTAINER_ID
stemctl mcp status
```
`mcp select` sprawdza registry, pełny ID i label kontenera, aktywnie testuje
serwery Neovima i tmuxa, a następnie jednym `rename(2)` przełącza symlink
`$XDG_RUNTIME_DIR/stem/mcp-selected/current`. Jeśli choć jeden serwer nie
odpowiada, poprzedni wybór pozostaje bez zmian.
Katalog socketów jest tworzony przez launcher na hoście i bind-mountowany do
kontenera pod identyczną ścieżką. Dopiero `nvim` i `tmux` działające w
kontenerze tworzą odpowiednio `n.sock` i `t.sock`; hostowy Codex łączy się z
tym samym plikiem przez widok hosta. Sockety nie są przekazywane przez sieć ani
nie dają kontenerowi dostępu do socketu Podmana.
Połączenia MCP mają profil `observe`, `assist` albo `full`. `full` jest
przeznaczony dla nauczyciela: może wykonywać dowolne działania dostępne w
Neovimie, tmuxie i terminalu wybranego kontenera jako konto ucznia. Profile
`observe` i `assist` muszą używać oddzielnych, ograniczonych providerów;
nie wolno udawać ograniczenia przez samą zmienną środowiskową przy providerze
udostępniającym ogólny Vimscript lub polecenia panea.
MCP nie jest czwartym kontenerem. Bridge jest częścią `dev-ui-base`, a hostowy
resolver jest częścią `stem-launcher`.
+46
View File
@@ -0,0 +1,46 @@
# Wytyczne dokumentowania debugowania
## Cel
Zrzut debuggera jest dowodem pomiaru, nie dekoracją. Ma pozwolić uczniowi
połączyć jedną operację w C z instrukcjami RISC-V, rejestrami, ramką stosu i
konkretnymi bajtami w RAM.
## Kadr dowodowy
- Używaj rzeczywistej sesji `stemctl debug` z karty, symulatora albo płytki.
- Zatrzymaj program w jednym nazwanym punkcie: breakpoint, checkpoint albo
instrukcja bezpośrednio przed obserwowaną operacją.
- Zachowaj wspólny układ: dashboard Termdebug/GDB po lewej, źródło C po
prawej, listing `.lst` pod źródłem. Listing musi być zsynchronizowany z PC.
- Pokaż tylko dane potrzebne do tezy: wywołanie w C, odpowiadającą instrukcję,
argument w rejestrze, fragment stosu albo pamięć w RAM.
- Dołącz podpis z platformą, taskiem i stanem pomiaru, na przykład „przed
pierwszym przydziałem pamięci”.
## Oznaczenia
- Stosuj najwyżej cztery krótkie oznaczenia numeryczne na jednym kadrze.
- Każdy numer ma odpowiadać jednemu zdaniu w podpisie lub legendzie.
- Bieżący kolor oznaczeń to czerwony: oznacza „zatrzymaj się i sprawdź”.
Paleta może później ulec zmianie, ale numeracja i podpis muszą pozostać
zrozumiałe bez koloru.
- Nie zasłaniaj kodu ani nie zmieniaj jego treści. Zachowaj surowy zrzut jako
źródło, a adnotowany obraz zapisz jako osobny plik.
## Wstawienie do karty
- Zasoby zapisuj w `doc/assets/`, np.
`task04-first-allocation-annotated.png`.
- W `doc/main.tex` umieść obraz blisko instrukcji, której dotyczy, oraz dodaj
zwięzły podpis wyjaśniający numery.
- Po zmianie zbuduj PDF skryptem `scripts/render_pdf.sh` i sprawdź stronę
wynikową w rozmiarze A4.
- W materiałach dla ucznia używaj słowa **RAM**, nie skrótu „SRAM”.
## Przykład referencyjny
Karta `inf/pointers`, Task04: `alloc_local(5)` przed pierwszym przydziałem.
Kadr pokazuje wywołanie C, `li a0,5` i `jal alloc_local`, wartość `a0=5` oraz
pusty `allocbuf`. Taki obraz dokumentuje związek źródła, ABI i pamięci bez
zastępowania go opisem narracyjnym.