STEM Launcher
stemctl jest hostowym wejściem do kart pracy, Git i trzech źródłowo
budowanych kontenerów STEM. Zdalne repo nosi kanoniczną nazwę
edu-tools/stem-launcher; Gitea przekierowuje historyczny URL rv-launcher,
a rvctl pozostaje cichym wrapperem zgodności.
Launcher nie pobiera i nie publikuje gotowych obrazów środowiska. Klonuje repo
narzędzi zawierające Dockerfile i docker-compose.yml, a brakujący profil
buduje lokalnie rootless Podmanem. Tag localhost/stem/...:local jest tylko
lokalnym wpisem cache runtime.
Model
| Profil | Targety | Zastosowanie |
|---|---|---|
native-amd64 |
native |
C/C++, golden tests, ASan/UBSan, GDB |
hazard3-sim |
hazard3-baremetal; hazard3-freertos po BSP timer/IRQ |
RTL Hazard3/Verilator bez płytki |
rp2350 |
rp2350-rv, rp2350-arm |
Pico 2/2 W, FreeRTOS, OpenOCD/picotool |
W każdym profilu interfejs pozostaje taki sam: tmux z prefixem Ctrl-s,
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,
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:
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
./stemctl workspace sync
./stemctl series list
./stemctl series cards fetch inf bss
./stemctl test native-amd64 inf bss 1
./stemctl test hazard3-sim inf bss 1
./stemctl debug hazard3-sim inf bss 1
./stemctl probe list
./stemctl deploy rp2350 inf bss 1 \
--target rp2350-rv --device /dev/bus/usb/001/006
Pierwsze wywołanie danego profilu może potrwać, ponieważ buduje go ze źródłowego Dockerfile. Kolejne korzystają z lokalnych warstw cache.
Pełną sesję lekcji można wybrać i kontrolować numerami z CLI:
./stemctl session choices --series inf --card 7 --task 4
./stemctl session reset hazard3-sim --series inf --card 7 --task 4 --step 12
./stemctl session refresh hazard3-sim --series inf --card 7 --task 4
./stemctl session attach hazard3-sim --series inf --card 7 --task 4
./stemctl session detach hazard3-sim --series inf --card 7 --task 4
current:0 jest domyślnym pane: pane 0 okna tmuxa, w którym działa
wywołujący Codex. session stage/session checkpoint ustawia dowolny etap UML
online w Termdebug albo tylko na stronie z --offline. Semantykę poleceń,
w tym podpinanie kontenera przez attach/detach, opisuje
referencja stemctl, a wybór checkpointów
dokumentacja sesji.
Wymuszenie samego przygotowania środowiska:
./stemctl env sync
./stemctl env build native-amd64
./stemctl env build hazard3-sim
./stemctl env build rp2350
env sync klonuje lub aktualizuje
edu-tools/rv32i-hazard3-student-env. Repo środowiska zawiera źródłowy
Dockerfile i pliki Compose.
Workspace
Domyślny układ:
~/dev/workspace/stem/
├── meta/workspace-info/
├── series/<seria>/<karta>/
├── tools/
│ ├── stem-launcher/
│ └── rv32i-hazard3-student-env/
└── 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.
Karta jest montowana jako całe /workspace, łącznie z przypiętymi źródłami
symulatora i trwałymi artefaktami:
~/dev/workspace/stem/series/<seria>/<karta>/
├── src/
├── vendor/Hazard3/
├── vendor/lab-runtime/
└── .stem/instances/.../build/
Przygotowanie i kontrola bez uruchamiania kontenera:
./stemctl env sources inf pointers
./stemctl env sources inf pointers --check
Każda zwykła akcja build/test/run/debug wykonuje przygotowanie automatycznie.
Launcher nie klonuje źródeł w kontenerze, nie tworzy symlinków do /opt i nie
nadpisuje zmodyfikowanego katalogu vendor/. Przypięcie pochodzi z
sources.lock.json repo środowiska.
Jeżeli istnieje tylko starszy ~/dev/workspace/rv, launcher wykrywa go bez
niszczenia danych. Jawna migracja:
./stemctl workspace migrate
./stemctl workspace doctor
Akcje i tożsamość instancji
Jedna logiczna instancja zachowuje nazwę między build, test, run,
debug i attach. Bieżący ID kontenera wchodzi natomiast do krótkiej ścieżki
socketu:
$XDG_RUNTIME_DIR/stem/<thread12>/<instance12>/<container12>/t.sock
$XDG_RUNTIME_DIR/stem/<thread12>/<instance12>/<container12>/n.sock
Resolver wykonuje podman inspect przed połączeniem i odrzuca osierocony
socket. Pozwala to jednemu Codexowi obsługiwać kilka kontenerów bez kolizji.
Stabilne wejścia MCP wymagają jawnej instancji i uruchamiają serwer znajdujący się w wybranym kontenerze:
./stemctl mcp tmux hazard3-sim-inf-bss-t1
./stemctl mcp nvim hazard3-sim-inf-bss-t1
Oddzielne wpisy klienta MCP mogą wskazywać inne nazwy instancji, więc jeden 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:
./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:
$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
Na komputer ucznia wchodzimy wyłącznie SSH z parą kluczy. Launcher, Git, rootless Podman i sockety działają na tym komputerze:
ssh uczen-lab
cd ~/dev/workspace/stem/tools/stem-launcher
./stemctl status hazard3-sim --instance lekcja-1
./stemctl debug hazard3-sim inf bss 1 --instance lekcja-1
Nie kopiujemy prywatnego klucza do kontenera. Jeżeli potrzebny jest zdalny GDB/MCP, używamy jawnego tunelu SSH albo wykonujemy klienta po stronie zdalnej.
Zgodność
Aliasy nadal działają:
host -> native-amd64
rv32i -> hazard3-sim
rvctl -> stemctl
RV_* -> fallback dla STEM_*
Nowe materiały powinny używać nazw kanonicznych.