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.

Dokumentacja

S
Description
stemctl workspace, container and lesson session control plane
Readme 279 KiB
Languages
Python 99.9%
Shell 0.1%