From b75c58875dea923cf0f5c318387dd32f920e4b73 Mon Sep 17 00:00:00 2001 From: KurbyDoo Date: Mon, 3 Aug 2026 01:54:09 -0400 Subject: [PATCH 1/2] fix whitespace issues --- CONTRIBUTING.md | 41 +++++++++---------------------- README.md | 27 +++++++++++++------- docs/branch-protection.md | 20 ++++----------- scripts/test-check.sh | 2 +- src/terrain_diffusion/__init__.py | 1 + src/terrain_diffusion/service.py | 28 +++++++++++++++++++++ tests/test_package.py | 1 + 7 files changed, 66 insertions(+), 54 deletions(-) create mode 100644 src/terrain_diffusion/service.py diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3da278f..a7e3ddf 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -14,6 +14,8 @@ scripts/quality-check.sh ``` +On Windows, run every `scripts/` command in Git Bash. PowerShell and Command Prompt cannot run bash scripts. See [onboarding.md](docs/onboarding.md) section 1 step 2. + Most formatting check failures can be enforced with: ```bash @@ -34,15 +36,11 @@ To run more specific tests, refer to the following commands. | `scripts/web-check.sh` | The visualizer in `web/`: lint, tests, and build. | -Testing on the Python side is done with pytest, and on the web side with vitest. We use pytest markers to categorize tests into three groups: `quick`, `slow`, and `gpu`. -`slow` and `gpu` tests are explicitly marked using `@pytest.mark.`, a test is categorized as `quick` otherwise. -You can use `test-check.sh` to run tests locally. Refer to the table above on how to invoke specific groups. +Testing on the Python side is done with pytest, and on the web side with vitest. We use pytest markers to categorize tests into three groups: `quick`, `slow`, and `gpu`. `slow` and `gpu` tests are explicitly marked using `@pytest.mark.`, a test is categorized as `quick` otherwise. You can use `test-check.sh` to run tests locally. Refer to the table above on how to invoke specific groups. -Anything after the group are treated as pytest args, so -`scripts/test-check.sh python -k sampler` passes the `-k sample` argument to pytest. +Anything after the group are treated as pytest args, so `scripts/test-check.sh python -k sampler` passes the `-k sample` argument to pytest. -You can also run pytest directly, as long as you go through uv so that the -project's environment is used: +You can also run pytest directly, as long as you go through uv so that the project's environment is used: ```bash uv run pytest @@ -80,9 +78,7 @@ For the frontend, run `pnpm add ` inside `web/` and commit the change t 7. Merge. -One thing to expect: pushing a new commit also removes any approval the pull -request already had, so it needs approving again. That is deliberate, so that -what gets approved is what gets merged. +One thing to expect: pushing a new commit also removes any approval the pull request already had, so it needs approving again. That is deliberate, so that what gets approved is what gets merged. The GitHub settings that make these checks compulsory are not stored in the repository. They are listed in [docs/branch-protection.md](docs/branch-protection.md). @@ -90,12 +86,9 @@ The GitHub settings that make these checks compulsory are not stored in the repo Every PR is expected to show some proof of testing for their work. This can be with unit tests or with new pytests added to one of the three groups below. -**Quick tests** have no marker on them. They run on every push and -decide whether a pull request is allowed to merge. Most tests should be in this -group. Write them so they stay fast. +**Quick tests** have no marker on them. They run on every push and decide whether a pull request is allowed to merge. Most tests should be in this group. Write them so they stay fast. -**Slow tests** are marked `@pytest.mark.slow`. They are left out when you push, -so they never hold up ordinary work. Run them on request, as described below. +**Slow tests** are marked `@pytest.mark.slow`. They are left out when you push, so they never hold up ordinary work. Run them on request, as described below. **GPU tests** are marked `@pytest.mark.gpu`. These will only run on the project's own GPU machine, on request. @@ -108,11 +101,7 @@ def test_core_model_runs(): ... ``` -The marker is what lets the GPU machine pick the test out and run it. The -`skipif` is what lets the test sit harmlessly in the suite everywhere else: on -a machine with no GPU it is reported as skipped instead of failing. Without -`skipif`, running the whole suite would fail for a reason that is not a real -problem with the code. +The marker is what lets the GPU machine pick the test out and run it. The `skipif` is what lets the test sit harmlessly in the suite everywhere else: on a machine with no GPU it is reported as skipped instead of failing. Without `skipif`, running the whole suite would fail for a reason that is not a real problem with the code. ## Running extra tests on a pull request @@ -130,14 +119,8 @@ request: Each comment runs its own job on the latest commit pushed to the branch, re-running a command while a job of the same type is running will cancel the previous run and start a new one on the latest commit. -Only people with access to this repository can use them. A short while after -commenting you should see a 👀 reaction on your comment, and then a reply with -the result. +Only people with access to this repository can use them. A short while after commenting you should see a 👀 reaction on your comment, and then a reply with the result. -The reply names the exact commit it tested. That matters: if you push more -commits afterwards, the old result no longer applies to the new code, and a -reviewer is meant to notice this and ask for the tests to be run again. +The reply names the exact commit it tested. That matters: if you push more commits afterwards, the old result no longer applies to the new code, and a reviewer is meant to notice this and ask for the tests to be run again. -These commands do not block merging on their own. Only the automatic checks do -that. Whether the extra tests were run is something the reviewer checks, using -the checklist in the pull request template. +These commands do not block merging on their own. Only the automatic checks do that. Whether the extra tests were run is something the reviewer checks, using the checklist in the pull request template. diff --git a/README.md b/README.md index 6623025..c81dab3 100644 --- a/README.md +++ b/README.md @@ -2,12 +2,9 @@ A reproduction of the [InfiniteDiffusion paper](https://arxiv.org/abs/2512.08309). -A game world like Minecraft lets a player walk in any direction forever, but the terrain looks blocky and artificial. -An AI image generator can paint a realistic landscape, but only one fixed size image, not an endless world. +A game world like Minecraft lets a player walk in any direction forever, but the terrain looks blocky and artificial. An AI image generator can paint a realistic landscape, but only one fixed size image, not an endless world. -This project produces a realistic, endless landscape from a seed. -A user chooses a seed, which is a number that fully determines the world, and explores the terrain in a 3D view. -The land has sharp ridges, river valleys, and coastlines, and it continues in every direction without end. +This project produces a realistic, endless landscape from a seed. A user chooses a seed, which is a number that fully determines the world, and explores the terrain in a 3D view. The land has sharp ridges, river valleys, and coastlines, and it continues in every direction without end. Two properties define it: @@ -18,24 +15,26 @@ The same seed always recreates the same world. The models are already trained by the paper's authors. Training terrain models of this kind costs thousands of dollars and takes months, so this project does not train them. It uses the released weights and rebuilds the algorithm that runs on top of them. Running a model needs about 2.2 GB of GPU memory, so a free cloud GPU or a gaming laptop is enough. +The project has its own machine, an RTX 2060 with 6 GB, confirmed able to serve the backend publicly through an outbound tunnel. What that machine can and cannot do is in [docs/machine-findings.md](docs/machine-findings.md), and it constrains a few things: latency will be several times the paper's figures, and there is about 3 GB of GPU memory spare rather than the whole card. + ## What we are building first The MVP: - As a user, I can give a seed and a region size and receive a height map image. - As a user, I can give a seed and a region size of more than one tile and get terrain whose tiles meet with no visible seams. -- As a user, I can give the same seed twice and get exactly the same terrain both times. +- As a user, I can give the same seed twice and get exactly the same terrain both times. Exactly means bit for bit on the same machine at the same precision. Across different machines, or between full and half precision, terrain matches within a small tolerance instead. - As a user, I can give a seed and a region and view the result as a 3D surface. ## How the system fits together -The system answers one question: what does the world look like at a given seed and coordinate. -It turns the answer into images and an interactive 3D view. +The system answers one question: what does the world look like at a given seed and coordinate. It turns the answer into images and an interactive 3D view. ```mermaid graph TD CLI["Output and CLI"] --> ORCH["Generation Orchestration"] - VIZ["3D Visualizer"] --> ORCH + VIZ["3D Visualizer"] -->|HTTP| API["Generation Service"] + API --> ORCH ORCH --> SAMP["Windowed Blending Sampler"] SAMP --> PIPE["Model Pipeline"] SAMP --> STORE["Terrain Store"] @@ -55,6 +54,7 @@ Which features live where: - The Windowed Blending Sampler holds the core generation math. - The Terrain Store holds memory behaviour, from bounded to lazy to infinite. - Generation Orchestration drives a region, and in the build-out coordinates the multi scale hierarchy. +- The Generation Service puts Orchestration behind HTTP, because the visualizer runs in a browser and cannot call Python directly. - Output and CLI and the 3D Visualizer hold user facing output. - Benchmarking and Evaluation holds paper comparison. @@ -70,6 +70,7 @@ Each component has one module. None of them are implemented yet, they hold the p | Windowed Blending Sampler | `src/terrain_diffusion/sampler.py` | | Terrain Store | `src/terrain_diffusion/store.py` | | Generation Orchestration | `src/terrain_diffusion/orchestration.py` | +| Generation Service | `src/terrain_diffusion/service.py` | | Output and CLI | `src/terrain_diffusion/cli.py` | | Benchmarking and Evaluation | `src/terrain_diffusion/benchmark.py` | | 3D Visualizer | `web/` | @@ -86,12 +87,20 @@ Install [uv](https://docs.astral.sh/uv/getting-started/installation/), the tool curl -LsSf https://astral.sh/uv/install.sh | sh ``` +On Windows, in PowerShell: + +```powershell +powershell -c "irm https://astral.sh/uv/install.ps1 | iex" +``` + Then install the project's packages: ```bash scripts/install-dependencies.sh ``` +> On Windows, run that in Git Bash. PowerShell cannot run bash scripts. [onboarding.md](docs/onboarding.md) section 1 has the full setup for all three systems. + > You do not need to install python, uv handles and maintains the correct python version. Check it worked: diff --git a/docs/branch-protection.md b/docs/branch-protection.md index 8678825..ed026f8 100644 --- a/docs/branch-protection.md +++ b/docs/branch-protection.md @@ -43,9 +43,7 @@ test web ``` -They may instead appear in the list as `CI / format`, `CI / test`, and -`CI / web`. Choose whichever version GitHub shows you. `web` passes until the -`web/` folder exists, and starts checking it once it does. +They may instead appear in the list as `CI / format`, `CI / test`, and `CI / web`. Choose whichever version GitHub shows you. `web` passes until the `web/` folder exists, and starts checking it once it does. Leave switched off: @@ -73,22 +71,14 @@ Leave switched off: - Workflow permissions: Read repository contents permission. Each workflow asks for anything more at the top of its own file. -If an organisation owns this repository, these settings also exist at -organisation level, and the stricter of the two applies. +If an organisation owns this repository, these settings also exist at organisation level, and the stricter of the two applies. ## 5. Add the GPU Machine `Settings -> Actions -> Runners -> New self-hosted runner` -Follow the instructions on that page. Add the label `gpu`. `self-hosted` is -applied automatically, and the workflow asks for both. +Follow the instructions on that page. Add the label `gpu`. `self-hosted` is applied automatically, and the workflow asks for both. -Then add `gpu` back to the `all` group in `.github/scripts/parse-command.sh`, -where a TODO marks the line. It is left out until the machine exists so that -`/test all` cannot wait on a runner that is not there. +Then add `gpu` back to the `all` group in `.github/scripts/parse-command.sh`, where a TODO marks the line. It is left out until the machine exists so that `/test all` cannot wait on a runner that is not there. -Until this is done, do not use `/test gpu`. GitHub allows a job to sit in the -queue waiting for a self-hosted runner for 24 hours before giving up, and the -hour long timeout on the job does not apply, because that limits how long a job -may run rather than how long it may wait. No result comment is posted until the -queue time runs out. \ No newline at end of file +Until this is done, do not use `/test gpu`. GitHub allows a job to sit in the queue waiting for a self-hosted runner for 24 hours before giving up, and the hour long timeout on the job does not apply, because that limits how long a job may run rather than how long it may wait. No result comment is posted until the queue time runs out. \ No newline at end of file diff --git a/scripts/test-check.sh b/scripts/test-check.sh index d7e615f..ab058a9 100755 --- a/scripts/test-check.sh +++ b/scripts/test-check.sh @@ -68,7 +68,7 @@ fi echo "==> Running the '$group' tests (pytest)" status=0 -uv run pytest "${marker_args[@]}" "${report_args[@]+"${report_args[@]}"}" "$@" || status=$? +uv run pytest "${marker_args[@]+"${marker_args[@]}"}" "${report_args[@]+"${report_args[@]}"}" "$@" || status=$? if [[ $status -eq 5 ]]; then if [[ "$group" == "python" ]]; then diff --git a/src/terrain_diffusion/__init__.py b/src/terrain_diffusion/__init__.py index e77e82d..d947698 100644 --- a/src/terrain_diffusion/__init__.py +++ b/src/terrain_diffusion/__init__.py @@ -8,6 +8,7 @@ sampler Windowed Blending Sampler store Terrain Store orchestration Generation Orchestration + service Generation Service cli Output and CLI benchmark Benchmarking and Evaluation """ diff --git a/src/terrain_diffusion/service.py b/src/terrain_diffusion/service.py new file mode 100644 index 0000000..87491b3 --- /dev/null +++ b/src/terrain_diffusion/service.py @@ -0,0 +1,28 @@ +"""Generation Service + +Overview + +Puts Generation Orchestration behind HTTP so the 3D Visualizer can reach it. + +The visualizer runs in a browser and cannot import Python, and Orchestration +runs on the machine holding the GPU. This component is the boundary between +them. It accepts a seed and a tile coordinate, asks Orchestration for the +region, and returns the height grid. + +Output and CLI does not go through here. It calls Orchestration in process. + +Neighbours and communication + +- Receives requests over HTTP from the 3D Visualizer. +- Asks Generation Orchestration for a region and returns the height grid. + +Notes for whoever builds this + +- The project machine sits behind carrier-grade NAT and reaches the outside + through an outbound tunnel, so the client address arrives in the + `Cf-Connecting-Ip` and `X-Forwarded-For` headers. The socket always reports + `127.0.0.1`. Anything that logs or limits by address has to read the header. +- Clients may be IPv6. The service itself can stay IPv4 only. +- There is one GPU with about 3 GB spare, so concurrent requests can exhaust + it. Serialising generation is the simplest answer. +""" diff --git a/tests/test_package.py b/tests/test_package.py index 2058838..d1981c0 100644 --- a/tests/test_package.py +++ b/tests/test_package.py @@ -16,6 +16,7 @@ "terrain_diffusion.sampler", "terrain_diffusion.store", "terrain_diffusion.orchestration", + "terrain_diffusion.service", "terrain_diffusion.cli", "terrain_diffusion.benchmark", ] From a3da29af48a92868b47ad27f91f4cad650fa7819 Mon Sep 17 00:00:00 2001 From: KurbyDoo Date: Mon, 3 Aug 2026 02:24:46 -0400 Subject: [PATCH 2/2] add introduction activity --- tests/test_introduction.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 tests/test_introduction.py diff --git a/tests/test_introduction.py b/tests/test_introduction.py new file mode 100644 index 0000000..363bf3a --- /dev/null +++ b/tests/test_introduction.py @@ -0,0 +1,35 @@ +"""Introductory file to get users familiar with tests and pull requests. + +Perform the following steps: +- Add your username to the user_list +- Add a test to the file below and name it test_ +- Assert something trivial. +- Run the bashs script ./scripts/test-check.sh +- Fix any and all errors that occur, rerun untill all are passing +- Create a pull request to add your changes. +""" + +import pytest + + +class TestIntroductory: + @pytest.fixture + def user_list(self): + return [ + # add your usernames here + "kurbydoo", + ] + + def test_kurbydoo(self, user_list): + assert 1 + 1 == 2, "Somthing went really wrong" + + n = 10 + counter = 0 + for i in range(1, n): + counter += i + + assert counter == n * (n - 1) // 2, "Check arithmetic sum" + + assert len(user_list) == 1 + + ### Add your tests below, follow the format above