From dfa39edfa0dd3f741f225a9a2ff706d6bf7c03fd Mon Sep 17 00:00:00 2001 From: 0xrsydn Date: Wed, 23 Sep 2026 18:32:49 +0700 Subject: [PATCH] build(dev): add pinned Nix and nix-direnv environments --- .envrc | 2 ++ .gitignore | 5 ++++ AGENTS.md | 3 ++ docs/DEVELOPMENT.md | 69 +++++++++++++++++++++++++++++++++++++++++++++ docs/MOD_SETUP.md | 8 ++++-- flake.lock | 27 ++++++++++++++++++ flake.nix | 55 ++++++++++++++++++++++++++++++++++++ 7 files changed, 166 insertions(+), 3 deletions(-) create mode 100644 .envrc create mode 100644 docs/DEVELOPMENT.md create mode 100644 flake.lock create mode 100644 flake.nix diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..381a6e6 --- /dev/null +++ b/.envrc @@ -0,0 +1,2 @@ +# Requires direnv with nix-direnv enabled in your user configuration. +use flake diff --git a/.gitignore b/.gitignore index 44b08ac..97c2d05 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,11 @@ __pycache__/ *.py[cod] +# Local nix-direnv cache and Nix build links +.direnv/ +/result +/result-* + # Machine state from bot runs -- reproducible, not source deck.json diff --git a/AGENTS.md b/AGENTS.md index 5674b36..6bec897 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -16,6 +16,9 @@ ## Checks Use Python 3.10+ from the repository root. Core Python code uses the standard library. +Use `direnv allow` with nix-direnv or `nix develop` for the pinned toolchain. +`nix flake check -L` runs the offline checks below in an isolated environment. +See `docs/DEVELOPMENT.md` for setup and platform limits. ```sh python3 test_facts.py && python3 test_brain.py && python3 test_run.py diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md new file mode 100644 index 0000000..6d4e41f --- /dev/null +++ b/docs/DEVELOPMENT.md @@ -0,0 +1,69 @@ +# Nix development environment + +The repository provides a locked development shell for `x86_64-linux` and +`aarch64-darwin`: the CachyOS desktop and Apple Silicon MacBook. The shell provides Python, .NET SDK 9, Git, Jujutsu, curl, and Bash. +`flake.lock` pins the package source for both desktop and laptop. + +## nix-direnv + +Enable flakes in Nix and configure direnv plus nix-direnv in your user environment. +The repository does not change your shell configuration. With Home Manager: + +```nix +programs.direnv = { + enable = true; + nix-direnv.enable = true; +}; +``` + +Ensure your interactive shell has the direnv hook enabled. Then, in the repository: + +```sh +direnv allow +``` + +The checked-in `.envrc` calls `use flake`. Review it before allowing it. +`.direnv/` is ignored. No credentials are loaded by `.envrc`. +The first activation can download substantial SDK dependencies. + +Without direnv: + +```sh +nix develop +``` + +## Offline checks + +```sh +nix flake check -L +``` + +This runs the three Python regression scripts, dataset integrity checks, and Bash +syntax checks. The check uses an isolated home and explicit source inputs. It +needs no game, credentials, model calls, or submodule checkout. It does not rebuild +the dataset. Nix can download dependencies before the offline check starts. + +For interactive checks in the shell: + +```sh +python3 test_facts.py && python3 test_brain.py && python3 test_run.py +python3 migrate.py --check-only +bash -n eval_batch.sh ab_card_skip.sh +``` + +The flake does not build or launch the game. Build the mod inside `nix develop` +or the direnv shell, using the local game path described in [MOD_SETUP.md](MOD_SETUP.md). +Proprietary game assemblies remain outside the Nix store. The private mod submodule +requires separate Git/SSH access, but the development shell does not fetch it. + +Live bot execution still needs the local mod API and separately configured model +credentials. `--dry-run` can make model calls; it is not an offline test. + +## Updating packages + +Run `nix flake update nixpkgs`, then repeat the offline checks and mod build. +Review and commit the lock-file update deliberately. Do not update dependencies +merely to enter the shell. + +The outputs support the listed systems, but a successful macOS check does not +prove Linux game integration. Run `nix flake check -L` on CachyOS too. diff --git a/docs/MOD_SETUP.md b/docs/MOD_SETUP.md index 00854cb..c05b1a1 100644 --- a/docs/MOD_SETUP.md +++ b/docs/MOD_SETUP.md @@ -32,7 +32,9 @@ revision changes require Git; ordinary bot changes can continue to use `jj`. ## Build on CachyOS / Linux -Install .NET SDK 9 and the native Linux Steam version of Slay the Spire 2. +Enter the pinned development environment with `direnv allow` (nix-direnv) or +`nix develop`. It includes .NET SDK 9; see [DEVELOPMENT.md](DEVELOPMENT.md). +Install the native Linux Steam version of Slay the Spire 2 separately. Check that `dotnet --list-sdks` lists a 9.x SDK. Set `GAME_DIR` to the actual Steam library path; custom libraries and Flatpak Steam use different paths. @@ -45,8 +47,8 @@ dotnet build vendor/STS2MCP/STS2_MCP.csproj -c Release \ -p:STS2GameDir="$GAME_DIR" -o /tmp/sts2-mcp-build ``` -If you already use Nix, you can replace `dotnet build` with -`nix shell nixpkgs#dotnet-sdk_9 --command dotnet build`. +Outside the shell, prefix the build command with `nix develop --command`. +This uses the repository lock file rather than your machine's nixpkgs registry. Build against your installed game assemblies. A successful Mac build does not prove compatibility with a different Linux game version. diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..631dde9 --- /dev/null +++ b/flake.lock @@ -0,0 +1,27 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1790046670, + "narHash": "sha256-MYiI+CzL0tuWgRPjGsKCDHqYs2T3OzMlMQWOYWG0qso=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "6774f7bc253789b113a4f39285dc0fa100abeacc", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..5f8cbec --- /dev/null +++ b/flake.nix @@ -0,0 +1,55 @@ +{ + description = "STS2 bot development and offline checks"; + + inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + + outputs = { nixpkgs, ... }: + let + systems = [ "x86_64-linux" "aarch64-darwin" ]; + forAllSystems = nixpkgs.lib.genAttrs systems; + packagesFor = system: import nixpkgs { inherit system; }; + in + { + devShells = forAllSystems (system: + let pkgs = packagesFor system; + in { + default = pkgs.mkShellNoCC { + packages = with pkgs; [ python3 dotnet-sdk_9 git jujutsu curl bash ]; + DOTNET_CLI_TELEMETRY_OPTOUT = "1"; + DOTNET_NOLOGO = "1"; + }; + }); + + checks = forAllSystems (system: + let pkgs = packagesFor system; + in { + offline = pkgs.runCommand "sts2-offline-checks" { + nativeBuildInputs = [ pkgs.python3 pkgs.bash ]; + # Explicit inputs exclude credentials, local captures, game binaries, + # and submodules. Only the committed regression fixtures are needed. + source = pkgs.lib.fileset.toSource { + root = ./.; + fileset = pkgs.lib.fileset.unions [ + ./facts.py ./brain.py ./jev.py ./sts2.py ./run.py + ./run_state.py ./recording.py ./migrate.py ./policy + ./test_facts.py ./test_brain.py ./test_run.py + ./eval_batch.sh ./ab_card_skip.sh + ./dataset ./capture/09_now.json + ]; + }; + } '' + export HOME="$TMPDIR/home" + mkdir -p "$HOME" + cp -R "$source" source + chmod -R u+w source + cd source + python3 test_facts.py + python3 test_brain.py + python3 test_run.py + python3 migrate.py --check-only + bash -n eval_batch.sh ab_card_skip.sh + touch "$out" + ''; + }); + }; +}