Repository navigation
Conversation
Replace the Python (Click/Rich/Pydantic) implementation with a single Rust binary. Every player command and every hooked cd used to cold-start a PyInstaller bundle; the Rust binary answers a cd hook in about 2 ms and is about 2 MB. - Levels are Rust builder code, one function per level, with the assignment prose in Markdown files compiled in. Custom checks are plain functions, so all 94 levels are declarative or use a small escape hatch. - Drop-in compatible with the Python save file (state.json v2.1), level IDs, workspace and marker layout. Game shells started by the old binary keep working through the legacy cd-hook forms. - Shell integration keeps protocol v1. The cd hook no longer needs a per-level dispatch list, evidence is recorded after the move, and fish `cd -` is fixed. - Tests replay every level's solution through the real binary in bash and fish, fresh and after a re-prepare, plus strict-cd, CLI, shell, state compatibility and rendering suites (1307 tests). - CI builds static Linux x86_64/aarch64 and macOS binaries. macOS assets stay unpublished until the macOS content review. `shellgame update` replaces the binary with the latest release. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Rust version replaces it entirely: sources, Python tests, packaging (pyproject, uv.lock, PyInstaller spec) and the Makefile. The golden-file helper scripts in tests/state/ stay; regenerating the files needs a checkout of the last Python release. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The rework this branch carried uncommitted:
- Levels are const struct literals, one file per section
(src/levels/s00_welcome.rs ... s11_search.rs), each opening with its
goals block; the engine moves from src/engine to src/game. Positions
("S.L") replace level ids and state.json v3 replaces the Python-era
v2.1: an older save is set aside as state-old.json.
- The game shell is confined by Landlock (src/sandbox.rs); without it the
game refuses to start unless run with --unsafe.
- ARCHITECTURE, AUTHORING, the specs and the shell protocol move into
AGENTS.md, module docs and .claude/skills; cargo doc is published as
the docs site. chrono, indexmap, terminal_size and assert_cmd are gone.
- The tests become the e2e (solution replays, playthroughs, strict cd),
cli, shell and sandbox suites.
Fixes from the review:
- reset repairs a workspace or section directory the player damaged
(lost permissions, a file or a symlink in its place, never followed).
- A parent directory without x no longer reads as a deleted one.
- A save of a newer version is an error; the notice about an older one
comes last and names the position to resume.
- hint -r shows the unlocked hints again; repeat is a hidden alias of
show; update has curl timeouts; setup errors are in Czech.
- Course: grading, leaked answers, wrong explanations and Czech wording
fixed in every section; answers that were only labels become a bare
submit. No level is added, removed or moved, so saved positions do not
shift.
- Tests: reset damage cases, save versions, a replay that fails on a
missing command, Landlock ABI and over-restriction steps, no pinned
wording; the validation also scans failed-check messages for answers.
- CI publishes only the tip of main, blocks a release on the bash 3.2
shell tests and smoke-tests the static binary in a confined game
shell; docs deploy after CI. install.sh is POSIX sh with
SHELLGAME_INSTALL_DIR and SHELLGAME_REPO.
Both parts changed the same uncommitted files, so they are one commit.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fish 3.3 (ubuntu-22.04) warns on every start when it cannot create ~/.config/fish and ~/.local/share/fish, and the sandbox forbids creating them in the home. The warnings failed every fish replay that runs there. A fish player's home has these directories: fish makes them on its first start. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The sandbox test points XDG_*_HOME into the test directory, where fish 3.3 cannot create its config and data directories under Landlock and warns about history, which the test rightly forbids. A fish player has these directories, as the test home now does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
main gained the `levels` and `resume` commands for the Python version (#2). This branch removes the Python implementation and has its own `levels` and `resume` (a bare `resume` also lists the levels), so the merge keeps this branch's tree: the Python files and tests main changed or added are dropped, and the README already documents both commands. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
It cut the answer out of `type shellgame`, which a Czech bash words as "shellgame je funkce". `type -t` prints "function" in every locale, in bash and fish. The level itself already accepts both words. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Students play in cs_CZ.UTF-8, which changes the output of tools the levels lean on (sort order, `ls --help`, bash's own messages), while the tests ran in C.UTF-8. SHELLGAME_TEST_LOCALE overrides the harness locale, and the lint leg replays every level in cs_CZ.UTF-8 as well. `cargo test --no-fail-fast`: a failing suite no longer hides the failures of the suites after it, which cost a CI round trip. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fish makes ~/.config/fish and ~/.local/share/fish on its first start, which the sandbox forbids; fish 3.3 (Ubuntu 22.04) then warns on every game shell start that history and settings will not be saved. The launcher, which is not confined, now makes them as fish would. Env gains the XDG config and data homes for that. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
clap's usage errors are English ("error: unrecognized subcommand
'sumbit'", and for `--shell zsh` the tip "a similar value exists:
'fish'"), which first-semester students meet with every typo. An
unknown command, an unexpected argument and an invalid value are now
told in Czech with clap's suggestion (or the valid values) and a pointer
to `shellgame --help`; help, the version and anything else are printed
as clap writes them. The exit status stays 2.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`line="${line%$'\r'}"` puts a literal CR into the function body, so
`type shellgame` (which the alias level asks students to run) garbles a
line on screen. The CR is now made with `printf -v`, which `type` shows
as text. bash 3.1 has `printf -v`.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Plain texts wrap at spaces, which split a quoted command such as 'ls -l' or 'file *' across rows in the narrow centred panels. A span in single quotes or backticks now stays whole when it fits a row. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bugs: - 8.7: the mode message told a player standing in `parent` to run `chmod u+x ..`, which changed the wrong directory and looped. It now names the directory they stand in and `chmod go-x .`, and the check accepts any mode with x for the owner only. - 5.6: `./calc.py` was rejected (suffix now) and `calc` gets a hint; the generic error no longer talks about the x permission. - 8.6: the missing-copy message names recovered.txt. - 1.3: `alpha`, submitted from inside alpha, no longer says to go there. Wording: - "není správně" agreement in sections 7, 9, 10 and 11; - 9.6 calls the second word "slovo z posledního řádku"; - 7.5 count errors point at the folders to count; - 9.11 explains a doubled line too; - 11.4 explains a path to the directory only; - 3.4 explains `.data`; - the fish alias note in 6.7; - the final screen is prose instead of a ragged checklist; - sections 6 to 11 use `###` headings like the others; - a too-wide line in the section 1 intro; - "Aktuální level" in the status screen; - smaller Czech fixes. No level is added, removed or moved. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Replaces the Python implementation with a single Rust binary. Three commits:
state.jsonv3;AGENTS.md, module docs and skills;What changes for students
shellgame update; they need to re-run the installer once.install.shis now POSIXsh, and its overrides are renamed toSHELLGAME_INSTALL_DIRandSHELLGAME_REPO.state-old.jsonand a new game starts. The notice names the command to continue, e.g.shellgame resume 5.3. A save from a newer version is refused, with a hint to runshellgame update.--unsafe: the game shell can change files only in/tmp, the state directory and/dev. Without Landlock (e.g. macOS, WSL 1, old kernels) the game refuses to start unless run with--unsafe.shellgame submit. New CLI:hint -r, pluslevels,resume,updateand--version.Review fixes in the last commit
resetrescue: it repairs a damaged workspace or section directory (lost permissions, a file or a symlink in its place, never followed). A parent directory withoutxno longer reads as "your directory was deleted".cd -drill counted from anywhere.3was wrong.find .paths, quoting and the format example.sgcollided with/usr/bin/sg.~keyboard help and bothls -ldiagrams.main, so an older build can't becomelatest;resetdamage, save versions,hint -rand a parent withoutx;Before merging
main: it has a69c0a4 (feat: addlevelsandresumecommands #2,levelsandresumefor the Python version). This branch replaces those files, so the conflicts should resolve in favour of this branch.workflow_rundocs deploy) have only run locally. Check this PR's run. Whether the arm64 runner has Landlock is unknown; without it the smoke test falls back to--unsafewith a warning.pwdbefore the finalcd.submitjoins its words with spaces.PUBLISH_MACOS).Test plan
Run locally on Linux with Landlock:
cargo fmt --check,cargo clippy --all-targets --locked -- -D warnings,RUSTDOCFLAGS="-D warnings" cargo doc --no-deps: clean.SHELLGAME_TEST_LANDLOCK=required cargo test --locked:cd, regressions)*.shpasses.resetafter each damage case, old/new saves,hint -r,repeat, and 2.2, 3.4, 6.7 and 11.5 in tmux.🤖 Generated with Claude Code