4 KiB
Canonical Commands
Load when: running Rust tests, Godot tests, sims, or builds. These must run FROM the EDIT host and execute ON the RUN host via ssh — never run the raw cargo/flatpak/build-gdext.sh commands directly on the EDIT host.
For env var setup (AUTOPLAY_HOST, PROJECT_ROOT_REMOTE, etc.) see two-host-workflow.md.
| Intent | Canonical command (from EDIT host) |
|---|---|
| Rust workspace tests | ssh "$AUTOPLAY_HOST" "cd $PROJECT_ROOT_REMOTE/src/simulator && cargo test --workspace" |
| GPU-feature tests | ssh "$AUTOPLAY_HOST" "cd $PROJECT_ROOT_REMOTE/src/simulator && cargo test -p mc-turn --features gpu" |
| Single crate | ssh "$AUTOPLAY_HOST" "cd $PROJECT_ROOT_REMOTE/src/simulator && cargo test -p <crate>" |
| GDExtension build | ssh "$AUTOPLAY_HOST" "cd $PROJECT_ROOT_REMOTE/src/simulator && bash build-gdext.sh" |
| WASM build (web guide) | ssh "$AUTOPLAY_HOST" "cd $PROJECT_ROOT_REMOTE/src/simulator && bash build-wasm.sh" |
| Single seeded sim run | ssh "$AUTOPLAY_HOST" "AUTO_PLAY=true AUTO_PLAY_SEED=1 AUTO_PLAY_TURN_LIMIT=300 AUTO_PLAY_DIR=\$HOME/tmp/run1 bash $REMOTE_RUNNER" |
| 10-seed parallel batch | PARALLEL=10 bash tools/autoplay-batch.sh 10 300 .local/iter/<stamp> (reads $AUTOPLAY_HOST; p1-45: auto-rebuilds GDExt before launch when running locally — CARGO_TARGET_DIR isolated per run) |
| GUT unit tests | ssh "$AUTOPLAY_HOST" "cd $PROJECT_ROOT_REMOTE/src/game && flatpak run --filesystem=home org.godotengine.Godot --path . --headless -s addons/gut/gut_cmdln.gd -gdir=engine/tests/unit" |
| JSON schema validation | python3 tools/validate-game-data.py (pure Python, runs on EDIT host) |
| Lint | gdlint src/game/engine/src/ (runs on EDIT host, no toolchain needed) |
Pair with ./run wrappers when available — see task-runner.md.
First-run on a fresh apricot scratch dir
Godot needs src/game/.godot/global_script_class_cache.cfg and src/game/.godot/extension_list.cfg to register class_name-declared GDScript classes (e.g. AiTurnBridge) and gdextension libraries (e.g. GdGridState, GdCity). These files are NOT committed and are NOT created by rsync; they're built by Godot on first project import.
If a fresh scratch dir on apricot (~/.cache/mc-src-<stamp>/) shows SCRIPT ERROR: Identifier "GdGridState" not declared in the current scope or Could not find type "AiTurnBridge", run a one-time import to build the cache:
ssh apricot 'cd ~/.cache/mc-src-<stamp> && timeout 60 flatpak run --user --filesystem=home org.godotengine.Godot --path src/game --headless --import 2>&1 | tail -5'
Subsequent runs (autoplay, GUT, batches) will then load extensions and class_name registrations correctly.
Async batch protocol on apricot (p2-64)
When apricot connectivity is intermittent (sleep/wake, sshd channel saturation, network blips), use the launch / status / fetch loop instead of the synchronous scripts/apricot-run.sh smoke … flow. The systemd --user unit on apricot owns the build+batch lifecycle and survives ssh disconnects. Status probes use a single short-timeout ssh and never read file contents — only is-active / ls | wc -l style checks.
STAMP=$(scripts/apricot-run.sh launch smoke 10 300) # bare stdout = stamp
while STATE=$(scripts/apricot-run.sh status "$STAMP" | jq -r .state); \
[[ $STATE != complete ]]; do
[[ $STATE == failed ]] && { echo "batch failed; journalctl --user -u mc-batch-$STAMP" >&2; exit 1; }
[[ $STATE == unreachable ]] && sleep 30 && continue
sleep 60
done
LOCAL=$(scripts/apricot-run.sh fetch "$STAMP") # rsync to .local/iter/<stamp>/
States: running (unit active), complete (completion.marker present), failed (unit inactive + no marker), unreachable (ssh probe timeout — retryable, no work lost).
Submodes currently wired into the launcher: smoke, clan, difficulty. Other modes (gpu-walltime, matchup-grid, huge-map-5clan, ai-quality-baseline*) still run via the synchronous flow and can be added to the launcher case-branch as needed.