docs: define host workspace and MCP access
This commit is contained in:
@@ -23,6 +23,23 @@ Neovim, Termdebug, nvim-dap oraz MCP tmuxa i Neovima. Kod karty, wyniki i
|
|||||||
artefakty są bind-mountem na hoście. Kontenery nie dostają kluczy SSH, tokenów,
|
artefakty są bind-mountem na hoście. Kontenery nie dostają kluczy SSH, tokenów,
|
||||||
socketu Podmana/Dockera ani całego `/dev`.
|
socketu Podmana/Dockera ani całego `/dev`.
|
||||||
|
|
||||||
|
## Pierwsza instalacja
|
||||||
|
|
||||||
|
Pierwszy klon launchera również należy do workspace. Nie uruchamiamy
|
||||||
|
`stemctl` z przypadkowego katalogu domowego ani z kontenera:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir -p ~/dev/workspace/stem/tools
|
||||||
|
git clone http://77.90.8.171:3001/edu-tools/stem-launcher.git \
|
||||||
|
~/dev/workspace/stem/tools/stem-launcher
|
||||||
|
cd ~/dev/workspace/stem/tools/stem-launcher
|
||||||
|
./stemctl workspace sync
|
||||||
|
```
|
||||||
|
|
||||||
|
Od tego momentu wszystkie komendy `stemctl`, karty i repozytoria odpowiedzi
|
||||||
|
pozostają pod `~/dev/workspace/stem`. Kontener dostaje wybraną kartę jako
|
||||||
|
`/workspace`, ale nie jest miejscem przechowywania źródeł.
|
||||||
|
|
||||||
## Szybki start
|
## Szybki start
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -69,6 +86,10 @@ Domyślny układ:
|
|||||||
└── tokens/tokens.json
|
└── tokens/tokens.json
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Pierwszym repozytorium w `tools/` jest `stem-launcher`; to ono pobiera
|
||||||
|
workspace-info, źródła kart oraz repo środowiska. Pozostałe repozytoria są
|
||||||
|
zarządzane przez `stemctl`, a nie klonowane wewnątrz kontenera.
|
||||||
|
|
||||||
Jeżeli istnieje tylko starszy `~/dev/workspace/rv`, launcher wykrywa go bez
|
Jeżeli istnieje tylko starszy `~/dev/workspace/rv`, launcher wykrywa go bez
|
||||||
niszczenia danych. Jawna migracja:
|
niszczenia danych. Jawna migracja:
|
||||||
|
|
||||||
@@ -102,6 +123,30 @@ się w wybranym kontenerze:
|
|||||||
Oddzielne wpisy klienta MCP mogą wskazywać inne nazwy instancji, więc jeden
|
Oddzielne wpisy klienta MCP mogą wskazywać inne nazwy instancji, więc jeden
|
||||||
Codex obsługuje kilka kontenerów bez globalnego „ostatniego socketu”.
|
Codex obsługuje kilka kontenerów bez globalnego „ostatniego socketu”.
|
||||||
|
|
||||||
|
Klient MCP działający stale na hoście może także przełączać oba narzędzia
|
||||||
|
atomowo przez wspólny wskaźnik `current`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./stemctl mcp list
|
||||||
|
./stemctl mcp select rp2350-pointers-final
|
||||||
|
./stemctl mcp status
|
||||||
|
./stemctl mcp select 3aca2c1c4c7a
|
||||||
|
```
|
||||||
|
|
||||||
|
Selektor przyjmuje nazwę instancji, nazwę kontenera albo co najmniej 12 znaków
|
||||||
|
ID. Weryfikuje ID i label przez `podman inspect`, a także aktywnie sprawdza oba
|
||||||
|
serwery. Dopiero wtedy atomowo przełącza:
|
||||||
|
|
||||||
|
```text
|
||||||
|
$XDG_RUNTIME_DIR/stem/mcp-selected/current/n.sock
|
||||||
|
$XDG_RUNTIME_DIR/stem/mcp-selected/current/t.sock
|
||||||
|
```
|
||||||
|
|
||||||
|
Wskaźniki prowadzą do katalogu zawierającego aktualny `container12`, więc
|
||||||
|
odtworzony kontener nie może przejąć socketów poprzednika. Neovim i tmux
|
||||||
|
otwierają nowe połączenie przy każdym wywołaniu narzędzia MCP, dlatego zmiana
|
||||||
|
działa bez restartowania klienta.
|
||||||
|
|
||||||
## Komputer zdalny
|
## Komputer zdalny
|
||||||
|
|
||||||
Na komputer ucznia wchodzimy wyłącznie SSH z parą kluczy. Launcher, Git,
|
Na komputer ucznia wchodzimy wyłącznie SSH z parą kluczy. Launcher, Git,
|
||||||
@@ -134,6 +179,7 @@ Nowe materiały powinny używać nazw kanonicznych.
|
|||||||
|
|
||||||
- [plan architektury](doc/architecture-plan.md)
|
- [plan architektury](doc/architecture-plan.md)
|
||||||
- [kontenery i interfejs](doc/containers.md)
|
- [kontenery i interfejs](doc/containers.md)
|
||||||
|
- [wytyczne dokumentowania debugowania](doc/debug-documentation-guidelines.md)
|
||||||
- [migracja nazw i workspace](doc/migration-stem-launcher.md)
|
- [migracja nazw i workspace](doc/migration-stem-launcher.md)
|
||||||
- [serie i karty](doc/series.md)
|
- [serie i karty](doc/series.md)
|
||||||
- [tokeny Gitea](doc/tokens.md)
|
- [tokeny Gitea](doc/tokens.md)
|
||||||
|
|||||||
@@ -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.
|
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
|
## Aktualny fundament
|
||||||
|
|
||||||
`rv32i-hazard3-student-env` dostarcza źródła wspólnego modelu:
|
`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
|
`stemctl` traktuje te pliki jako szczegóły implementacyjne. Użytkownik i agent
|
||||||
dostają komendy wyższego poziomu.
|
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 pane’a 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
|
## Role profili
|
||||||
|
|
||||||
Profil `hazard3-sim`:
|
Profil `hazard3-sim`:
|
||||||
|
|||||||
@@ -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
|
artefaktu. Bez niego odmawia wykonania, chyba że użytkownik jawnie zaakceptuje
|
||||||
istniejący firmware. Zapobiega to testowaniu starego programu.
|
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
|
## Instancje i sockety MCP
|
||||||
|
|
||||||
Stabilna nazwa logiczna:
|
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
|
zweryfikowanego kontenera. Neovim MCP publikuje również stan i komendy
|
||||||
Termdebug/nvim-dap.
|
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 pane’a.
|
||||||
|
|
||||||
MCP nie jest czwartym kontenerem. Bridge jest częścią `dev-ui-base`, a hostowy
|
MCP nie jest czwartym kontenerem. Bridge jest częścią `dev-ui-base`, a hostowy
|
||||||
resolver jest częścią `stem-launcher`.
|
resolver jest częścią `stem-launcher`.
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
Reference in New Issue
Block a user