TiGa-RCE commited on
Commit
623f6f8
·
verified ·
1 Parent(s): e63a295

Refresh single-engine training UI, track map, and short-lived results

Browse files

Update to upstream b90b8af6 CI artifacts; keep CPU private and GPU Protected. Replace stale dual-engine files with the bounded runner, browser recipes and built-in track map. Results expire after five minutes; server retention is opt-in per single run.

This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .dockerignore +0 -6
  2. .gitattributes +1 -42
  3. BETA_TESTING.md +4 -4
  4. BINARY_PROVENANCE.json +18 -18
  5. DATA_POLICY.md +15 -13
  6. Dockerfile +0 -24
  7. FRONTEND_SOURCE.json +4 -4
  8. PACKAGE_MANIFEST.json +0 -328
  9. README.md +4 -12
  10. RELEASE_MANIFEST.json +19 -15
  11. STORAGE_BOUNDARY.md +1 -1
  12. UPSTREAM.json +2 -3
  13. ZEROGPU_MANIFEST.json +0 -10
  14. assets/track-atlas.json +1 -0
  15. backend_policy.py +0 -21
  16. batch_runner.py +0 -42
  17. bin/altd-sim +2 -2
  18. bin/libaltd_gpu.so +2 -2
  19. client.js +8 -5
  20. cloud-contract.json +0 -1
  21. cloud_core.py +0 -5
  22. cloud_probe.py +0 -63
  23. delivery.py +2 -2
  24. demo.evolution +0 -0
  25. github-simulator/source/Cargo.lock +0 -792
  26. github-simulator/source/Cargo.toml +0 -77
  27. github-simulator/source/GODOT_LICENSE +0 -43
  28. github-simulator/source/LICENSE +0 -21
  29. github-simulator/source/README.md +0 -183
  30. github-simulator/source/assets/models/formula.json +0 -73
  31. github-simulator/source/assets/models/rally.json +0 -74
  32. github-simulator/source/assets/networks/formula.json +0 -31
  33. github-simulator/source/assets/networks/rally.json +0 -31
  34. github-simulator/source/assets/random_track_settings.json +0 -7
  35. github-simulator/source/assets/scenes/formula_template.json +0 -111
  36. github-simulator/source/assets/scenes/rally_template.json +0 -112
  37. github-simulator/source/assets/scenes/snowmobile_template.json +0 -123
  38. github-simulator/source/assets/scenes/truck_template.json +0 -112
  39. github-simulator/source/docs/cli.md +0 -115
  40. github-simulator/source/docs/design.md +0 -59
  41. github-simulator/source/docs/fidelity.md +0 -37
  42. github-simulator/source/docs/gpu.md +0 -31
  43. github-simulator/source/docs/math-profiles.html +0 -415
  44. github-simulator/source/docs/performance.md +0 -72
  45. github-simulator/source/docs/reviews/2026-10-05-native-server-review.md +0 -51
  46. github-simulator/source/docs/server.md +0 -102
  47. github-simulator/source/docs/superpowers/specs/2026-10-05-native-server-design.md +0 -322
  48. github-simulator/source/docs/wasm.md +0 -27
  49. github-simulator/source/gpu/README.md +0 -105
  50. github-simulator/source/gpu/benchmark.py +0 -117
.dockerignore DELETED
@@ -1,6 +0,0 @@
1
- __pycache__
2
- **/__pycache__
3
- *.pyc
4
- **/target
5
- .cache
6
- runs
 
 
 
 
 
 
 
.gitattributes CHANGED
@@ -1,42 +1 @@
1
- *.7z filter=lfs diff=lfs merge=lfs -text
2
- *.arrow filter=lfs diff=lfs merge=lfs -text
3
- *.bin filter=lfs diff=lfs merge=lfs -text
4
- *.bz2 filter=lfs diff=lfs merge=lfs -text
5
- *.ckpt filter=lfs diff=lfs merge=lfs -text
6
- *.ftz filter=lfs diff=lfs merge=lfs -text
7
- *.gz filter=lfs diff=lfs merge=lfs -text
8
- *.h5 filter=lfs diff=lfs merge=lfs -text
9
- *.joblib filter=lfs diff=lfs merge=lfs -text
10
- *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
- *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
- *.model filter=lfs diff=lfs merge=lfs -text
13
- *.msgpack filter=lfs diff=lfs merge=lfs -text
14
- *.npy filter=lfs diff=lfs merge=lfs -text
15
- *.npz filter=lfs diff=lfs merge=lfs -text
16
- *.onnx filter=lfs diff=lfs merge=lfs -text
17
- *.ot filter=lfs diff=lfs merge=lfs -text
18
- *.parquet filter=lfs diff=lfs merge=lfs -text
19
- *.pb filter=lfs diff=lfs merge=lfs -text
20
- *.pickle filter=lfs diff=lfs merge=lfs -text
21
- *.pkl filter=lfs diff=lfs merge=lfs -text
22
- *.pt filter=lfs diff=lfs merge=lfs -text
23
- *.pth filter=lfs diff=lfs merge=lfs -text
24
- *.rar filter=lfs diff=lfs merge=lfs -text
25
- *.safetensors filter=lfs diff=lfs merge=lfs -text
26
- saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
- *.tar.* filter=lfs diff=lfs merge=lfs -text
28
- *.tar filter=lfs diff=lfs merge=lfs -text
29
- *.tflite filter=lfs diff=lfs merge=lfs -text
30
- *.tgz filter=lfs diff=lfs merge=lfs -text
31
- *.wasm filter=lfs diff=lfs merge=lfs -text
32
- *.xz filter=lfs diff=lfs merge=lfs -text
33
- *.zip filter=lfs diff=lfs merge=lfs -text
34
- *.zst filter=lfs diff=lfs merge=lfs -text
35
- *tfevents* filter=lfs diff=lfs merge=lfs -text
36
- tracks/R06[[:space:]]Mix.track filter=lfs diff=lfs merge=lfs -text
37
- tracks/R07[[:space:]]Mirage[[:space:]]Marina.track filter=lfs diff=lfs merge=lfs -text
38
- tracks/R09[[:space:]]Eau[[:space:]]Noir.track filter=lfs diff=lfs merge=lfs -text
39
- tracks/The[[:space:]]Champions[[:space:]]Trial.track filter=lfs diff=lfs merge=lfs -text
40
- bin/altd-sim filter=lfs diff=lfs merge=lfs -text
41
- bin/libaltd_gpu.so filter=lfs diff=lfs merge=lfs -text
42
- bin/extract_saved_track filter=lfs diff=lfs merge=lfs -text
 
1
+ bin/* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
BETA_TESTING.md CHANGED
@@ -1,7 +1,7 @@
1
  # Small-group beta entry gate
2
 
3
- Current status: local UI/CPU testing is useful now. The expanded runner interface
4
- has not yet been qualified on the hosted HF GPU runtime. Do not describe it as a
5
  stable release or invite a broad audience to an unqualified build.
6
 
7
  ## Protected beta address
@@ -47,13 +47,13 @@ Before remote testers receive the expanded interface:
47
  A stop/error must remain visibly different from a complete batch.
48
  - Create/edit/export/re-import a small network. Inspect or edit a known weight
49
  and verify the exported value. Modified artifacts must not inherit old scores.
50
- - Exercise default deletion, manual repeat downloads/delete, browser-only re-save,
51
  result expiry, invalid files, missing files and connection failure.
52
 
53
  Current supported worker contract: Formula steering/acceleration, speed/raycast
54
  sensors, 2–4 layers with at most 16 nodes per layer, and bounded execution.
55
  Inspection can show larger networks, but that is not permission to train them.
56
- The track map remains an intentional placeholder. Star challenges are explicitly
57
  not evaluated. No driving improvement or real-game/leaderboard parity follows
58
  from a successful artifact lifecycle test. A bucket and broad network support
59
  remain separate work.
 
1
  # Small-group beta entry gate
2
 
3
+ Current status: local UI/CPU testing is useful now. The refreshed runner interface
4
+ requires hosted CPU and GPU qualification before inviting a broad audience. Do not describe it as a
5
  stable release or invite a broad audience to an unqualified build.
6
 
7
  ## Protected beta address
 
47
  A stop/error must remain visibly different from a complete batch.
48
  - Create/edit/export/re-import a small network. Inspect or edit a known weight
49
  and verify the exported value. Modified artifacts must not inherit old scores.
50
+ - Exercise default deletion, opt-in repeat download, manual delete, browser-only re-save,
51
  result expiry, invalid files, missing files and connection failure.
52
 
53
  Current supported worker contract: Formula steering/acceleration, speed/raycast
54
  sensors, 2–4 layers with at most 16 nodes per layer, and bounded execution.
55
  Inspection can show larger networks, but that is not permission to train them.
56
+ The track map previews selected tile layouts and terrain, including custom uploads, but does not show collision geometry. Star challenges are explicitly
57
  not evaluated. No driving improvement or real-game/leaderboard parity follows
58
  from a successful artifact lifecycle test. A bucket and broad network support
59
  remain separate work.
BINARY_PROVENANCE.json CHANGED
@@ -1,22 +1,22 @@
1
  {
2
- "source_space": "TiGa-RCE/ald-tao-gpu",
3
- "source_revision": "ba07e35a39211af7a0deda0ebd9adb2c554b4f38",
4
- "upstream": "d8ab74c25df70b6a86ed101080e33d5fb785ea6f",
5
- "image_config": "sha256:31f7854e5fac0b54679eed2899c8951cd96571650ea6c74c27e2400a8c4aa6d3",
6
- "artifacts": [
7
- {
8
- "file": "bin/altd-sim",
9
- "sha256": "2f2f2144ae14b0ef599ca8510f95712da00243c6875881491d384b394e7499f7",
10
- "bytes": 13911800,
11
- "layer": "sha256:d4f213ac74fe7556e8ef4d71aa6195a80dd619057697748f2f3863c0aa1cbca7",
12
- "member": "app/github-simulator/source/target/release/altd-sim"
13
  },
14
- {
15
- "file": "bin/libaltd_gpu.so",
16
- "sha256": "279d6353b4c691686d6aeeae6abfd4a82b959e9b604f079a6c45f9823b48a87a",
17
- "bytes": 3933424,
18
- "layer": "sha256:c61e59a8a076ae00d64a4b8c55102f2ba9643dbe165cd66130ed662e131982ce",
19
- "member": "app/libaltd_gpu.so"
 
20
  }
21
- ]
 
22
  }
 
1
  {
2
+ "source_revision": "b90b8af06ffc4ea4e4fd703becd1107a48b8e5e0",
3
+ "source_repository": "https://github.com/Zorro909/driving_sim_rs",
4
+ "github_actions_run": 38203558700,
5
+ "run_conclusion": "success",
6
+ "importer_source_revision": "d8ab74c25df70b6a86ed101080e33d5fb785ea6f",
7
+ "artifacts": {
8
+ "bin/altd-sim": {
9
+ "sha256": "0135ecc3d435a9d327be7a92e048cfb5c5291a02ef1e0dddd6ead1cc19b31166",
10
+ "bytes": 15774792
 
 
11
  },
12
+ "bin/extract_saved_track": {
13
+ "sha256": "3a7733c45b4301a786fcbfe92660a1c484749272da5f608d62f34878bd4ff31a",
14
+ "bytes": 3247776
15
+ },
16
+ "bin/libaltd_gpu.so": {
17
+ "sha256": "0064e747543251bab90cb966f8df00b010716a92cc75910229d42c9b24c1dac9",
18
+ "bytes": 12291032
19
  }
20
+ },
21
+ "note": "altd-sim and GPU library from the same successful upstream Actions run; importer was built and smoke-checked separately; hosted runtime acceptance is a separate check"
22
  }
DATA_POLICY.md CHANGED
@@ -1,6 +1,6 @@
1
  # Data handling & deletion policy — private integration test
2
 
3
- Operator: TiGa (seeker-cyber-maker). Version: local runner candidate 2026-10-09.
4
 
5
  Files are processed only for the requested job, not collected for our own
6
  training, analytics or public examples. Inputs remain in the browser until Run.
@@ -28,14 +28,18 @@ Each job uses temporary files removed before a successful result is published.
28
  The application result store is memory-only. No public file URL is created.
29
  The browser holds a random job access key in memory, independently of optional HF sign-in.
30
  Anyone who obtains that key can access the job; do not share it. Reloading the
31
- page loses access. Expiry is fixed at 30 minutes from result publication.
32
 
33
- Automatic deletion is enabled by default. The browser validates the complete
34
- download and acknowledges receipt; that deletes the result store's copy. One
35
- download attempt is permitted. We cannot verify that the browser saved to disk.
36
- An interrupted attempt is not retryable in automatic mode; Delete now and expiry
37
- still work. Unchecking automatic deletion allows repeat downloads until expiry.
38
- Delete now removes the stored result immediately. Downloads never reset expiry.
 
 
 
 
39
 
40
  Access is refused at the deadline. While the server is running, the expiry loop
41
  releases expired stored data within approximately one second, subject to runtime
@@ -70,8 +74,8 @@ The browser retains its received result in page memory so Save received result
70
  again can retry a local save without another server retrieval. Discard browser
71
  result clears the app's reference; closing or refreshing the page loses it.
72
  No bucket support, network sandbox or provider-wide ZDR guarantee is offered.
73
- The service uses one result-owning process. Public deployment and its
74
- framework/proxy behavior must be tested separately before release.
75
 
76
  The runner candidate has a separate browser-local recipe library. Saving is
77
  explicit; settings and reward mixes, recipe names, and batch recipe references
@@ -87,9 +91,7 @@ result deletion and browser result discard.
87
  Batch execution freezes the selected recipes when Start is pressed. It runs
88
  sequentially, using either the original network each time or the preceding
89
  candidate. Each intermediate result is downloaded to browser memory, checked by
90
- size and SHA-256, and acknowledged for server deletion before the next run. Batch
91
- intermediate results always use automatic deletion regardless of the single-run
92
- checkbox. Only the last received candidate is retained in page memory for saving.
93
  Stop batch prevents the next run; it does not interrupt the current server job.
94
  Closing/reloading the page does not prove cancellation of an in-flight job.
95
  Failure to acknowledge a received result stops the batch and leaves Delete now
 
1
  # Data handling & deletion policy — private integration test
2
 
3
+ Operator: TiGa (seeker-cyber-maker). Version: HF runner refresh 2026-10-12.
4
 
5
  Files are processed only for the requested job, not collected for our own
6
  training, analytics or public examples. Inputs remain in the browser until Run.
 
28
  The application result store is memory-only. No public file URL is created.
29
  The browser holds a random job access key in memory, independently of optional HF sign-in.
30
  Anyone who obtains that key can access the job; do not share it. Reloading the
31
+ page loses access. Expiry is fixed at five minutes from result publication.
32
 
33
+ Automatic deletion is the default. The browser validates the complete download
34
+ and acknowledges receipt; that deletes the result store's copy. One server
35
+ download attempt is permitted in the default mode. We cannot verify that the
36
+ browser saved to disk. An interrupted default-mode download is not retryable;
37
+ Delete now and fixed expiry still work. Visitors can opt in for each single run
38
+ to keep its result in application memory for repeat downloads until the same
39
+ five-minute deadline. The checkbox resets after every run. Batch runs always
40
+ use automatic deletion. Delete now removes a stored result immediately, and
41
+ downloads never reset expiry. The browser can also save its received result
42
+ again from page memory.
43
 
44
  Access is refused at the deadline. While the server is running, the expiry loop
45
  releases expired stored data within approximately one second, subject to runtime
 
74
  again can retry a local save without another server retrieval. Discard browser
75
  result clears the app's reference; closing or refreshing the page loses it.
76
  No bucket support, network sandbox or provider-wide ZDR guarantee is offered.
77
+ The service uses one result-owning process. HF framework and proxy behavior may have retention outside this app, so this is
78
+ an application-level near-zero-retention design, not a provider-wide ZDR claim.
79
 
80
  The runner candidate has a separate browser-local recipe library. Saving is
81
  explicit; settings and reward mixes, recipe names, and batch recipe references
 
91
  Batch execution freezes the selected recipes when Start is pressed. It runs
92
  sequentially, using either the original network each time or the preceding
93
  candidate. Each intermediate result is downloaded to browser memory, checked by
94
+ size and SHA-256, and acknowledged for server deletion before the next run. Batch results always use automatic deletion, regardless of the single-run retention choice. Only the last received candidate is retained in page memory for saving.
 
 
95
  Stop batch prevents the next run; it does not interrupt the current server job.
96
  Closing/reloading the page does not prove cancellation of an in-flight job.
97
  Failure to acknowledge a received result stops the batch and leaves Delete now
Dockerfile DELETED
@@ -1,24 +0,0 @@
1
- FROM rust:1.93-bookworm AS build
2
- WORKDIR /build
3
- COPY github-simulator/source /build
4
- ENV RUSTFLAGS="-C target-cpu=x86-64"
5
- RUN cargo build --locked --release --no-default-features --features cli
6
- FROM nvidia/cuda:13.0.0-devel-ubuntu24.04 AS cuda
7
- RUN apt-get update && apt-get install -y --no-install-recommends python3 g++ && rm -rf /var/lib/apt/lists/*
8
- WORKDIR /build
9
- COPY github-simulator/source /build
10
- ENV CUDA_ARCH=sm_75,sm_86
11
- RUN bash gpu/build-cuda.sh
12
- FROM nvidia/cuda:13.0.0-runtime-ubuntu24.04
13
- RUN apt-get update && apt-get install -y --no-install-recommends python3 && rm -rf /var/lib/apt/lists/*
14
- RUN useradd -m -o -u 1000 user
15
- WORKDIR /app
16
- COPY --chown=user:user . /app
17
- COPY --from=build --chown=user:user /build/target/release/altd-sim /app/github-simulator/source/target/release/altd-sim
18
- COPY --from=cuda --chown=user:user /build/target/gpu/libaltd_gpu.so /app/libaltd_gpu.so
19
- RUN chown user:user /app
20
- USER user
21
- ENV ALD_DASHBOARD_PORT=7860 PYTHONUNBUFFERED=1
22
- ENV ALD_REQUIRE_GPU=1 ALTD_GPU_LIB=/app/libaltd_gpu.so
23
- EXPOSE 7860
24
- CMD ["python3","server.py"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
FRONTEND_SOURCE.json CHANGED
@@ -1,8 +1,8 @@
1
  {
2
- "source": "User-provided local combined dashboard index.html",
3
  "source_sha256": "65d1e5f2c4e19b4951b828e82510005ab99a5270cf3dcb9f4eaa0fa1af8c40f8",
4
- "output_sha256": "135a0c57be851af2879660ae6584a4bfa0a9280fc33e2c0372bc47b531f1960f",
5
  "scope": "Frontend only; no engine, private data, track assets, API calls or storage copied",
6
- "status": "Local candidate: configurable training, browser recipes, bounded sequential batches, browser network editor; track renderer and star evaluation unconnected",
7
- "candidate_sha256": "24fd848cd38d84d84236558e1d617d79554ae462317b3bea68b11c74d2802076"
8
  }
 
1
  {
2
+ "source": "Runner r14 single-engine browser UI; selected .track tile renderer added from simulator atlas",
3
  "source_sha256": "65d1e5f2c4e19b4951b828e82510005ab99a5270cf3dcb9f4eaa0fa1af8c40f8",
4
+ "output_sha256": "d329965febb49db4939093ec0c512474db109a7b3a24e97cbabb18f97674757b",
5
  "scope": "Frontend only; no engine, private data, track assets, API calls or storage copied",
6
+ "status": "Refresh candidate: track and terrain preview connected; star evaluation remains unconnected",
7
+ "track_atlas_sha256": "d97c8900e3e5fb17734b5bd61d1f4f4b196d9be30af9848e2e273ae7e4079ae4"
8
  }
PACKAGE_MANIFEST.json DELETED
@@ -1,328 +0,0 @@
1
- {
2
- ".dockerignore": "640b480c91c572b6d77411d9165f786a095d04fe5bc5b74e983ab6831aa4ba23",
3
- ".gitattributes": "478a5f208decd29019ad7be4fba9fdffe25a4a4c9c652032e98e4cf3cbd6ef97",
4
- "Dockerfile": "c592ca9eb888525821563ddb2707ecba0eeea3b06adfbe1aaa5e811339d032a7",
5
- "README.md": "e7ed341a32da89a48dd5194ede7d3066fea0700aab2752f1886f23b7970d6ca8",
6
- "UPSTREAM.json": "73d973fe445d7b51caea4980f35902f393c84720c8a256fd11622f84bb843806",
7
- "backend_policy.py": "3991fb88e25bebb9c36b49c0547af4e4630738c504e0c7b58a5917081deea5fe",
8
- "batch_runner.py": "c14777da239116a8025f800d59b33b307bf62fcfb80e3bcb59fdf81104a7c742",
9
- "cloud-contract.json": "ac4d1946a278d3cf3aae6d750249603adfd89f3c421eda4c62bb69e2bbf7490f",
10
- "cloud_core.py": "be517e165180baf610f6cb7e863bc76a6704233118952045a0366d72000d821a",
11
- "demo.evolution": "2743e838371d737f3309c47dc84bc7b43f13657f4b008b2b6eb6f4b429531920",
12
- "github-simulator/source/Cargo.lock": "d8b8dfcfd4ddd90388a9aadae6c12a675e46277a3f26dabcce5ba8af6ff12183",
13
- "github-simulator/source/Cargo.toml": "fe4d592043df0b10f6699dcf6fe6cc7b588ed3df23bfadae11afb61924f25bd9",
14
- "github-simulator/source/GODOT_LICENSE": "fb2b3bb82c60f1e76841ba2122eb902f8e39c151476fe21ce10c9a05d1045304",
15
- "github-simulator/source/LICENSE": "53d5851b6440feeae36f72a5f57fcab37858c48b7084765ece4b0c54b9a28ed8",
16
- "github-simulator/source/README.md": "cc11a5a17701416fbf11b392be303e0485aa308170ef2bf2f52815f60cac15de",
17
- "github-simulator/source/assets/models/formula.json": "fc7849fac5e20a14427ca8adafd4dab61518920d385411a144a8798ae02de2ed",
18
- "github-simulator/source/assets/models/rally.json": "5155711ab44e1db4aee6d3cb509d321e60d2a4ffabe1937603b3dd9daf187e1f",
19
- "github-simulator/source/assets/networks/formula.json": "452647361c18ee196c7abd1059c384f9281ca57890135e5b164f9669fe45250c",
20
- "github-simulator/source/assets/networks/rally.json": "75ecde48a073d1f343ced743955ffc3a7eaffcd035884452ce408b4d12707932",
21
- "github-simulator/source/assets/random_track_settings.json": "a0c3daae1436e659a3157fcb1e4520d5a59c16f739eb6a9eb53b397862cf7179",
22
- "github-simulator/source/assets/scenes/formula_template.json": "80f745df82bb7be45af52785fd582460bcddc63c5a4e1d8375d85b3122db4c6b",
23
- "github-simulator/source/assets/scenes/rally_template.json": "7350a3fe28d9b4da7a0965ae6ea7ca3472fb7885303e342310d63a0dce80851c",
24
- "github-simulator/source/assets/scenes/snowmobile_template.json": "12d30545876011fd6fccdd3e721f9c465938c9c58ac99338205481d5e7ac6742",
25
- "github-simulator/source/assets/scenes/truck_template.json": "a83bffea4d5e818c135ab3aba68a47aa288d6ad0e7b8bd9c95ed0dea9e9df2f7",
26
- "github-simulator/source/docs/cli.md": "095468c685d68362880323cd0aea56c0951517d2b9f5dbc281b67499e712cf28",
27
- "github-simulator/source/docs/design.md": "5e768d010d41f021aca8bc88119709a87fe4b346aed95d31b24bb1563c7974fd",
28
- "github-simulator/source/docs/fidelity.md": "1a58be54cc167aba2f8f78992382f3ae58005dfb7ecd6f7dd552466f10d66f54",
29
- "github-simulator/source/docs/gpu.md": "ecdd400d988344da2a076db2b32a09d06b3578d44c6b17da67c151b2dfbecff7",
30
- "github-simulator/source/docs/math-profiles.html": "69f7e3c9165e6c3c969805e77669ca0b13965a4e2b23c4a6e4dd8e234a9755f7",
31
- "github-simulator/source/docs/performance.md": "fa47013ff2940458a951250166b8b4f1c406cd99734d979c701aea7b2792cca3",
32
- "github-simulator/source/docs/reviews/2026-10-05-native-server-review.md": "4ed44f436e4348591d8728659d94e00f48bd8a2d559fda7c3fe2c695831e5b85",
33
- "github-simulator/source/docs/server.md": "4b8899b87ba53008b66eeb878794b961f10d16280134f4716453efcab347e37a",
34
- "github-simulator/source/docs/superpowers/specs/2026-10-05-native-server-design.md": "99ac6ee8e335ab71ddcfdd28ab4ed2d7d1cfbad7935101d72ebe39fe017fdf6b",
35
- "github-simulator/source/docs/wasm.md": "888386a1b77546382c7ba39d4897e62b83015c6ce2ef725b436b6561031b47ef",
36
- "github-simulator/source/gpu/README.md": "e831018c053fd7a47162d89b72b789d8c5ecd455e46f57282b23be2f9c460a43",
37
- "github-simulator/source/gpu/benchmark.py": "413db669422dba553e54adcf083aa11372c7925232a02a23a96aef8b55954380",
38
- "github-simulator/source/gpu/build-cuda.ps1": "dc5b4dbdf277c8522fe927f13db6e68df1554ccf5ecf78cb79128d34a1c63550",
39
- "github-simulator/source/gpu/build-cuda.sh": "a1d64a98c968dffde896e6634914ae7312820ff04171bc29ddc4519f112c8a6d",
40
- "github-simulator/source/gpu/build.sh": "563dfba35d55d33e1340fc80bd063931cc88129ff2214cc556d7205c71308183",
41
- "github-simulator/source/gpu/gen_tables.py": "f0fe3dbcefa271a63093c1c7ee7c5c55166bdfd96a3daa0e7113ea37da0f6e2e",
42
- "github-simulator/source/gpu/profile.sh": "f08fbab3a38ed6414548009e1b116f7cc289ea67d1baef7262c1c886926bde88",
43
- "github-simulator/source/gpu/release-targets": "fdca8679baa13af1191fbc0179201e8aafdf7355ba8c5684ea378b6afeffe1a2",
44
- "github-simulator/source/gpu/sim/altd_gpu.hip": "212f169713fd96a065822ef3c6fe712491a144b0cb1b63df0f083967f509065e",
45
- "github-simulator/source/gpu/sim/compat.h": "23c60db69ca371dd8da6a7949911a6f69d52250448a3623e73a5c3c290331ff8",
46
- "github-simulator/source/gpu/sim/double_tables.h": "472dbcd916293dcd91dcd3f882ba86ed36267ede819ffb1692daf8b6ad5a38ec",
47
- "github-simulator/source/gpu/sim/engine_exceptions.h": "4568607466a307d1520d763ea2f1c7424219299caf365ffa03dd62084673a551",
48
- "github-simulator/source/gpu/sim/math.h": "ae93aadb2d49492176a08a1bed4a1c5b687f99ae16da57736ef30661dcaaeb8b",
49
- "github-simulator/source/gpu/sim/rays.h": "414fc93b6a5180c9ed906a0b802eea48a5d81bba8920097989dfa568bfa82f12",
50
- "github-simulator/source/gpu/sim/sensors.h": "64390b210bf388abb49026ba0b8529144eb025b0d306fb3198745b345fe38942",
51
- "github-simulator/source/gpu/sim/state.h": "3672b2e48d43e6696cb9a61abff7a1de6a131dc2b7cbf6d99413596565a1bb20",
52
- "github-simulator/source/gpu/sim/stats.h": "dc0d785dceaa06e27d90f5aa2a4513eb75aea6d149bbfde9ed8965f79c233d82",
53
- "github-simulator/source/gpu/sim/step.h": "022390d8f2eb5276969826c5b650dba05de9ffc9264f03c1cee012060693bec7",
54
- "github-simulator/source/gpu/sim/track.h": "2dcb2a8ae356115965a5047cf3843e0bdb9c547e0b297b9ab87772385549184c",
55
- "github-simulator/source/gpu/sim/vec.h": "715afdaaff174668892bc5ada76edab317445a770bc0d6e7e0e0e83cb459740c",
56
- "github-simulator/source/gpu/sim/world.h": "cff41441c08ff645384d972ec56412122b5a38ff5d618e09c979870f70d15f6f",
57
- "github-simulator/source/gpu/test_constructor_cleanup.py": "bdd1fc42aa1494e20558f8c7ce20a9ca4a3775aeae4c836fd9688581f5bb87e6",
58
- "github-simulator/source/math/README.md": "33b210248e6ed5c4abe4104940abc27fd1728af2a5af07bf442c1dfa2bd4caf4",
59
- "github-simulator/source/math/fixtures/atan2f.bin": "9ecf9251878ddcb789a43119f1f060e24025db3e3485cccdbcb1f4366cb68ed2",
60
- "github-simulator/source/math/fixtures/cosf.bin": "c84017673fdbe2a29f03e8ae4f410292da3ee93f5f74d91e169053a04c6273d6",
61
- "github-simulator/source/math/fixtures/exp.bin": "b0b063fc5bba32294b399f7305718a15797f4df65ba81cfbc785264e11126a9a",
62
- "github-simulator/source/math/fixtures/log.bin": "9ef1de3473a7b1d8a2416eee3f2263a88eea073ad9c2af53bb751bca7e45813c",
63
- "github-simulator/source/math/fixtures/pow.bin": "d2475d6b050e7b842f868c093591b4095509cd2e1350ba8ebb06df64452bf3cc",
64
- "github-simulator/source/math/fixtures/sinf.bin": "bae316adc7a9ceb4a61a8375a7eb94004d9e9058e5563cc81e14c9ffe911a104",
65
- "github-simulator/source/math/fixtures/tanh.bin": "b0f438bcf53c685c622158e0ab2f47b9a2c714e8c35cb8b90da1e539a53c7e2c",
66
- "github-simulator/source/math/kernels/ucrt.h": "cf0787112fc4f3cadd88d965ba69f9250ea6fced7ab33fe2a3d669caae5dda5a",
67
- "github-simulator/source/math/kernels/ucrt_tables.h": "0f2fd20c1513b5c88c6a138cdabdedfa68d652d07f6f19910e1a6a8a290af028",
68
- "github-simulator/source/math/verification.md": "419e78815edbc8e47e3a39919d973a399cfa2d97b1556ac25fdfdd71540431c1",
69
- "github-simulator/source/src/bin/altd-sim/args.rs": "9f833f026d1f71ef76fe05d948464c619c76c15e43cedc11b5f510bfc337bda2",
70
- "github-simulator/source/src/bin/altd-sim/bench.rs": "76ddf4778cfafa0e8f2f821605c876fd250f2df37ef0d025028e7acaafc6ea0f",
71
- "github-simulator/source/src/bin/altd-sim/comparisons.rs": "9e6859b759f5f0f181e3a0130478237187472a242d2b615d545cb3d19aad7c6e",
72
- "github-simulator/source/src/bin/altd-sim/inputs.rs": "7c9c1b814dc9c072c2f77399836421c54547ef3029a2626f32c717434ef9c51d",
73
- "github-simulator/source/src/bin/altd-sim/io.rs": "e90bd9b1dd7028d5187872bed08763e7ee8437a80b1491cd9a9bcfb8c47fcc97",
74
- "github-simulator/source/src/bin/altd-sim/main.rs": "841956a5a1a927b1a31369ccbd9aa18161b6328745a5a3ca4f02bdcfedd7230c",
75
- "github-simulator/source/src/bin/altd-sim/platform.rs": "da8d6ffbf03990ed04e9fe8ac6ccecc1c5f5da292708eebd2f68621043b882d0",
76
- "github-simulator/source/src/bin/altd-sim/scratch/checkpoint.rs": "408f4c8438f8d8a8db2dd3888a55a7390a89723d1af1656ab7399897bf207eb5",
77
- "github-simulator/source/src/bin/altd-sim/scratch/mod.rs": "524e9033a1fb29ac7b4d689a21fede12b7bb77a772c078fce4c0bf4763568bbe",
78
- "github-simulator/source/src/bin/altd-sim/scratch/runner.rs": "20a78bd99dc6bd69cc9314ba2d531dac13b5d9f21fb6ca676d34c0fa472a46c0",
79
- "github-simulator/source/src/bin/altd-sim/scratch/stop.rs": "b13d0b473376b0fb90d71d82713ae79d862337f5b1d874c1d53fa14ecf677c50",
80
- "github-simulator/source/src/bin/altd-sim/scratch/tests.rs": "c59cbe78aca660ee9327c316d260e3d18cfbf302f41430e1985856090409a740",
81
- "github-simulator/source/src/bin/altd-sim/train.rs": "7397016461d6d8a6642f03a2466d9bf22f1daabc1ab74ab22aaf7212821e23f1",
82
- "github-simulator/source/src/data/tilemap_initial_cells.json": "97b5c28b80993f263e35fe22279944a91e7016f6f1471ef05317239c655acb53",
83
- "github-simulator/source/src/data/track_catalog.json": "b1f71cd4c15aee7dcd81897ebe8549115bb270a26dc33728e9c5a4546f4408fe",
84
- "github-simulator/source/src/data/track_resources.json": "e8b23c8a98f9c0c6573044ab0e7a01e8f707e6c46b234e96f9834a5370a61fab",
85
- "github-simulator/source/src/gpu/hip.rs": "6618d96c39049e95a8dee98aa9656d27b1998ac71dd15fdb036210fedd68884f",
86
- "github-simulator/source/src/gpu/mod.rs": "c8be62ad28ac998af80ebc9f5fb06320f8b791ab7f8a53db47c72b496506a7ae",
87
- "github-simulator/source/src/gpu/simulation.rs": "3da4252813c8d7e83d48858a67b0f1a64ca75c274f4d930f656f80bc6e509b05",
88
- "github-simulator/source/src/lib.rs": "a5d365de4631e9d4f7e1d049307f510c315dd74bb6a9ad6dec0e4e12a5c72138",
89
- "github-simulator/source/src/math/double_math.rs": "9e5cce0ab7ab000ad2a40bd0315a09bc3af7910db97bc9296a8813b36ee6804b",
90
- "github-simulator/source/src/math/double_math_tables.rs": "d27b8bbb61a1493efabb0a6a24dc095568fe096e4e34ba58470aefcdeb9735e2",
91
- "github-simulator/source/src/math/float_reduction.rs": "21a5b0a46ecebe0c7fcb7bdeb1c9d3ae2589bc1796573615e8e00f2a1674d0ed",
92
- "github-simulator/source/src/math/godot_math.rs": "5537ed27280374a776615baa9bfe8a134c479d38a15cacb9cba1dccb4e0c9d50",
93
- "github-simulator/source/src/math/managed_sine_tables.rs": "fc4534f09a984ad78ca64f5584a2c2c868291841ff96f35353b8f82e89c31d8a",
94
- "github-simulator/source/src/math/managed_trig.rs": "7497fdc77380ffc09dfea7921a938906cd12f6831faca118ad745c70053fc8c2",
95
- "github-simulator/source/src/math/mod.rs": "c94f7656088d04220b5d59a9d28a340843f3f101fb39baec5aa48411d2290fd7",
96
- "github-simulator/source/src/math/native_math.rs": "67efb2ce5a45c69c13006aa8b37c52ab3feb807b2d4b1e0d6bf04738e2ce8414",
97
- "github-simulator/source/src/math/profile.rs": "df925dfdd799fed5691865c272e3e0ec1dea5bdd5961663edce4ccbd8c962d0c",
98
- "github-simulator/source/src/math/pymath.rs": "ccadf6379fd4f4c7ba38e3c5aaab5e09d6d3f0388a7861a5c4525c70e7852357",
99
- "github-simulator/source/src/math/ucrt.rs": "5cb27a66798d592f053ee1ecd8b5cc71a5cf250c31d2cbfbe00eb194fa4a57a4",
100
- "github-simulator/source/src/math/vec2.rs": "18111a5d6412b7e4d6010c90d36f1892dd5553611b0c0778cea44db26b527afc",
101
- "github-simulator/source/src/nn/mod.rs": "56200ce58b1191aadf594a44d2d967eb8ecd0e19d5f0d68b1299fdefd5d49e12",
102
- "github-simulator/source/src/nn/network.rs": "af897658264b6bcc0c0cb4c6218da28a417fdee82b3531b90f833bab59502ca3",
103
- "github-simulator/source/src/nn/network_simd.rs": "b4339e7da61d54aa617098981c3e27bb4757bac160f6d39c5c7bbb0c5ab86e60",
104
- "github-simulator/source/src/physics/broadphase.rs": "65e90c5bbdd975b7dfa4ab9f81130e36a21df28f04faf193213c8522c39a837b",
105
- "github-simulator/source/src/physics/car.rs": "b47eee90cd42d1bb9c9f8f98b1794ec85c3e3ca13b862d053f2dcc8048dab615",
106
- "github-simulator/source/src/physics/collision.rs": "eb4b3ccc9d668a8054b843bd31624dd5602bd3db92c01f11dda8d8852a1d4a31",
107
- "github-simulator/source/src/physics/mod.rs": "f24b54fe129527d6032bfda7f24704db6abc500130cc0d499937593dd4a61b48",
108
- "github-simulator/source/src/physics/simulation.rs": "730da7a2a910f924cb23e2c4f67f9e59ac822ca3011596766953cf6188617e4f",
109
- "github-simulator/source/src/physics/trace_state.rs": "83ac2de24529f195c506f90445ffef8e6c03d4d310264509d2a8ac915cc59699",
110
- "github-simulator/source/src/server/dispatch.rs": "cf5206817e1eb2bcf52ae1a55f5cafde5d4b3583638eb6f8a250dfc933c29a82",
111
- "github-simulator/source/src/server/mod.rs": "17672296ff7e9c6562443a913bdf290a12688b23bdadd61d57982ec40eb522e5",
112
- "github-simulator/source/src/server/protocol.rs": "05b17adc585357659bd301495bd2026a39f52faa45fca61eb94fc42bc16c29c1",
113
- "github-simulator/source/src/track/bsp.rs": "1555c30fdc8f1c2f68a877986095c6bb5146546e82394ed2c412bb89bade8be3",
114
- "github-simulator/source/src/track/curve.rs": "b01a5d140b92a8eca03bfe7ca1d58fcf5e8455388d394b2f86d3094d98352b00",
115
- "github-simulator/source/src/track/mod.rs": "4548f19925c2f61fac6a076ddbafacd062b29b75c8eecffcd7d7eb3037482900",
116
- "github-simulator/source/src/track/path_segments.rs": "afa22462a3c5486d5bd9873313786cbb3aa28b932293fbebce37721ad9add24c",
117
- "github-simulator/source/src/track/random_track.rs": "f60118f42f04b257188f89199956bad52139727ed4cff4376377a7bfb64d56e6",
118
- "github-simulator/source/src/track/segment_grid.rs": "636b56c997ee10c5a56ed19a06f8525ff1e7a0756fbdc4dd4a73f8a02534f642",
119
- "github-simulator/source/src/track/training_tracks.rs": "af7207f94db09f8e5d221844de25bb2a7fba44e82cacaa973c58e058a95332a3",
120
- "github-simulator/source/src/track/world.rs": "81b4fab7ad2030629859cd7d725461b4e6adf6667f88b68629d289e8eb18fe52",
121
- "github-simulator/source/src/training/agent.rs": "e3c0362788b7a23e47104d897c1d12025c8658f361c79f6328db0504c9416e02",
122
- "github-simulator/source/src/training/ars.rs": "74672f1717b1eeea227e3f04479bbb951dc8289850a25e0c8ca59cecd6b77218",
123
- "github-simulator/source/src/training/ars/tests.rs": "4273896832a470a0f10dd7c913b07726d21e3dceb6b7786abc89a195ecee05fe",
124
- "github-simulator/source/src/training/batch_evaluation.rs": "6b975431eac59bfb197f3e5632ad58e1baa86c96f272360d351a4908df896f23",
125
- "github-simulator/source/src/training/evaluation.rs": "66a6b86cdd3a052be533271a0012fb38a5a2ca2f973644681d013350f0b5ea27",
126
- "github-simulator/source/src/training/evolution.rs": "d050036c9346561411feefc6c94d598cb0f3ee69e85a8960cf911d60b2129a61",
127
- "github-simulator/source/src/training/game_random.rs": "04e90273f4960b36dbbba831bc4f95390998e31fd874fc3cca308580fe59228b",
128
- "github-simulator/source/src/training/lineage.rs": "35ae0755d172ce54b7e26682ff626ef71d4ab724c553a2bb958084540d257c42",
129
- "github-simulator/source/src/training/mod.rs": "8ef89fe999edd56502e85aba2b20664ab63871b9a03977c5c4b40293d945d905",
130
- "github-simulator/source/src/training/optimizer.rs": "ee0ccc79494840e566e919d75879c2ceddd126fe5b5b49622f8c8d08af4aca92",
131
- "github-simulator/source/src/training/pyrandom.rs": "1890f3338964d87e892589fea12d673ff181b2945ad7c121ecc0cde586e9d758",
132
- "github-simulator/source/src/training/runner.rs": "5dcac344de3256dd27c6dead9cee92ab6ec1e782db38409002c7540fa11f2d42",
133
- "github-simulator/source/src/training/runner/gpu.rs": "12475cb92731f5e9c311a9ca62c4e17f0dfde17bc46efe9f827f6ba4a91ebbac",
134
- "github-simulator/source/src/training/runner/rays.rs": "e6467baf46fb091e81ca40aaa0ccc5b0f316f264cd8871e2a7f897cc4ae75320",
135
- "github-simulator/source/src/training/runner/schedule.rs": "7bae3c881f2f2b086f1007734008056fcedab3316626cd9a5b13909daec02890",
136
- "github-simulator/source/src/training/runner/tests.rs": "26fe931db6894bd72813136daf77fe0991307d1d715ffceea5f0e398e3e05b86",
137
- "github-simulator/source/src/training/sensors.rs": "c3fe5cf32fb6ae0f75eaf08d826b482d3002ba9871a17e5c9b224c37cc9eda7c",
138
- "github-simulator/source/src/training/session.rs": "608545b42d523766492d58e927b77e1beb5f4914476480ea5e64d0c325d62289",
139
- "github-simulator/source/src/training/session/hip.rs": "a498f4712d2482d4229869748e3958c2ed502309b33e3465ac939d6d50ab3b2b",
140
- "github-simulator/source/src/training/session/input.rs": "8d2ae4c9121a0a561797dbd394493c73a012d1687fbd5248ced4aa06c49eae90",
141
- "github-simulator/source/src/training/stats.rs": "94075a6d675927b083c734e36049d12ec3faed67cb420e9a4c35e1de15a2a764",
142
- "github-simulator/source/src/training/training_profile.rs": "2f801070e7e5b93fa774f2fe253642940f605167c8bb8a9e5f697e9dbacc36bc",
143
- "github-simulator/source/src/wasm/float.wgsl": "6bfd8df71111352061ae5da4c6a0d496cfa3ff801a9c9ac9346a8dd940225584",
144
- "github-simulator/source/src/wasm/gpu.rs": "065e78fe19c01f9ce4f09ff370d47696f77c3f53512fe54bb3d239f3a2860567",
145
- "github-simulator/source/src/wasm/math_profile.rs": "63a59813aeb49686fa20ced1f0f379338ac12bffcda5d124f32abaa6a8fa524c",
146
- "github-simulator/source/src/wasm/mod.rs": "96caf3e5bd084cbfb16e589430c952c6f4713fd843a63d3ca087d1b6aa391f2d",
147
- "github-simulator/source/src/wasm/rays.wgsl": "0717e2a36bab9dd88cf2225104f6a5db198b767e9e4997ad40681a9bdf567448",
148
- "github-simulator/source/src/wasm/sim/f64.wgsl": "b171bed33b9761f90ffd8222c36ff2532e9a260ff706fa85a10fb6f3ccb7cc46",
149
- "github-simulator/source/src/wasm/sim/generated.wgsl": "a2f2947ecbd4b7eef088e074cf339c99e485c0d6c03365502686e3f9c80b0cf2",
150
- "github-simulator/source/src/wasm/sim/helpers.wgsl": "bded7a38f12f5f5b37ccebb9e5a0701b476d353dad5f1cde230d97cae30e2737",
151
- "github-simulator/source/src/wasm/sim/mod.rs": "1f4f7d45024a70768c6f0ff771991eadfb844118c0b64b17305f3ae40df611b7",
152
- "github-simulator/source/src/wasm/sim/runtime.js": "fa6094b141f2db440d9627eb5eb203ed01a7670c3f3ba3933cc72cf49a046834",
153
- "github-simulator/source/src/wasm/sim/window.wgsl": "532b56c9dd694381269513e0aec5831244aa7e5eb5dfdacf8ff66ec35b649f30",
154
- "github-simulator/source/src/wasm/sim/world.rs": "76ebd261bb47ffe59f671451df00a769bc450c595780abeabfe542ed2aa31954",
155
- "github_adapter.py": "7555cff8bceab47777386ee90a50074befa3711c433ad22cdca2ad4c1f652b3b",
156
- "godot/assets/imported/A01 Beginner.model.json": "1d46f92b1c7d91af75e9f16423194f0fce5453d78b2cc0e7fb18eeb1842b5dd8",
157
- "godot/assets/imported/A02 Sharp Turns.model.json": "40dbec0a1fa0bb029524cc71e0b420fe7dbcb7f4135a1f9ac21e1a6cd32786dc",
158
- "godot/assets/imported/A03 High Speed.model.json": "2e7406e4292259a3bddf66c92dca6bf37237d80694cf6a68003744d179bf22bb",
159
- "godot/assets/imported/A04 Dirt.model.json": "2dbcd29b0db5344dc2ae81be60c352a2dbddc3f2ac7b3427d2b76a8512d9733d",
160
- "godot/assets/imported/A05 Two Terrains.model.json": "562b16348c0d79dfa5a22f483922acedd36446461bf44d2e4f94693f4910c58f",
161
- "godot/assets/imported/A06 Ice.model.json": "56ccc3fa4149f3be4b25b5808482ca21edfcbf9559d497ff6fdb300aea14c76c",
162
- "godot/assets/imported/A07 Three Terrains.model.json": "e0dad6f3dfdb8261e7a88b584a8120b69573634403c411ab48b9c69648d453e9",
163
- "godot/assets/imported/A08 Long.model.json": "304998ba1effaecdfe8d9fcdaf59d8811db779c877458c454b355f70ad142d65",
164
- "godot/assets/imported/A09 Sharpest.model.json": "a6948598cad6238f0c5802d67e1be56bb1748b648dfff675d23f6a61a05d0f56",
165
- "godot/assets/imported/B01 Oval.model.json": "921fedb31214281dff3a64717da07abc6d85bb1bf0679411768c623a2dde02e9",
166
- "godot/assets/imported/B02 Snake.model.json": "b319d59a1a21ca094ce50b781938e108582de7752036e5da0c028447964f462d",
167
- "godot/assets/imported/B03 Slalom.model.json": "43008c2ea7475da7319f882a11a58d185ad093e46e002e5325eddbf80b00887a",
168
- "godot/assets/imported/B04 Rally.model.json": "d5458902717421ab99680f8106de6472425b34f85a8e7842fdc639be442a6c1b",
169
- "godot/assets/imported/B05 Racetrack.model.json": "203217155ac7d3d37e3bce4bf50199cfdece32a75533557435e78f3b1375f1d1",
170
- "godot/assets/imported/B06 Hard.model.json": "c4460d0bddedd7d4be6d00976b6554994476d68bec39684a680cd6019cd32e7c",
171
- "godot/assets/imported/B07 Drift.model.json": "d5b8b4418b84fe8a9d20f90e65abb1600510e122905b5eaa3e9d4f942549c97e",
172
- "godot/assets/imported/B08 Arctic Circle.model.json": "e9b12a0194692bd90980ade5e5d852eb91ab43a55522a9cfb997c79811d4131a",
173
- "godot/assets/imported/B09 Checkered.model.json": "183036504d32c8dfc1a58bae183d64501c629ab5c40e31908da4784cbdef8e0c",
174
- "godot/assets/imported/R01 Blitzring.model.json": "3b0ec1c62d4d75f1ff7a27e8bcfc7e88495de97482037d213a5d661ca8249855",
175
- "godot/assets/imported/R02 Desert Rally.model.json": "d3794fc462b24b6eaadd17f88c50fd98843cbae5b63f5e9765f9997e0244e04b",
176
- "godot/assets/imported/R03 Glacier.model.json": "ec9b3c8201c8f7546c366c1aa9715dc76d875acbe5c0b0771c4abf0a25270d36",
177
- "godot/assets/imported/R04 Truck Maze.model.json": "3ce6b887fdbf31a98e581715d77f7101251a1225e52bc072d0e8642a5d5e2fbe",
178
- "godot/assets/imported/R05 Endurance 500.model.json": "19529f1a12cf2c5cd9ca5f1f9479e7323eb598d7db6b12332d16bf69f561c33e",
179
- "godot/assets/imported/R06 Mix.model.json": "bee132139cf13457e293ce8cffe81ca8e8d5885e3276eea5a65465cc53594531",
180
- "godot/assets/imported/R07 Mirage Marina.model.json": "b541eb4cd0cd714dff4e7e5e493e15ea0a01d99a6aa3a65b4a97044a87003a09",
181
- "godot/assets/imported/R08 Demolition Derby.model.json": "b391029ce0b19f3ba6dea0831e53838337710136c9433ef84fce80317f4c9c07",
182
- "godot/assets/imported/R09 Eau Noir.model.json": "25b9bf89b5ebb2fac8d18a547a1086d37f92563ff667b6cfa2a3afff83e4539d",
183
- "godot/assets/imported/The Champions Trial.model.json": "9230869539197143ace6762107286000dba2cc050e6d35df7ef1d0c13fb5dc9b",
184
- "index.html": "78e54dd9173c70d57b15003bf44f69f2a299c2e12b64216d9cedfca6f4177ca3",
185
- "network_legality.py": "90196a2a6366768dda19fbb91dc03b2eeffa913b9af2ebffd33baa8f7a5067ec",
186
- "preset_store.py": "c0edd11430c93d7015373d3e8579c0781e1a4ff51372808aed7872247d84b735",
187
- "reward-catalog.json": "53b25e10a9e14b2ab1bd27259ca93d8fb0d49c4e27b3987f0ba2fc572bc63bf6",
188
- "server.py": "02f6cf7fe207ae0a2e008eba27d12a10020384338b17c7b4f4e9dd9f9520de0f",
189
- "tracks/A01 Beginner-compatible.track": "c52056d88edf9bebb9d3daf6f9839ddf67deb43ff93d93a93fb0fbb3566993c1",
190
- "tracks/A01 Beginner.saved.json": "23c93ec4443c269978ede5901b4c66a3f627cc273f3b5f6fa96d8a190a7e365b",
191
- "tracks/A01 Beginner.scene.json": "d79cc49de2a5dce8690cf3422ac74b76f3980f845f98235188a443a717cd1f10",
192
- "tracks/A01 Beginner.spawn.json": "c491511a8202b0bb4ba996c9f96a8d579dc30b443f5ff09984a18c5daee2ad89",
193
- "tracks/A01 Beginner.track": "d3261eda8f6cbf73c55fb55ced0404aa6cba162fbf24bdc7780638b23c29d6ed",
194
- "tracks/A02 Sharp Turns.saved.json": "cab708be9732a30f67d6cb3f2c639260844b003744ab061c6b06f5986024cb6d",
195
- "tracks/A02 Sharp Turns.scene.json": "ded6165101f191332485a311f453537816248adb177822558dd86d917db882cd",
196
- "tracks/A02 Sharp Turns.spawn.json": "03f1c1a3e2c720643e64f812a7bd619da8bc9ef27c108ab29be6fea982880763",
197
- "tracks/A02 Sharp Turns.track": "ade4031c6292f0342008a3479948bb32ed6f95235d74b5a4d0fe2762fdf9790f",
198
- "tracks/A03 High Speed.saved.json": "f21aa853ba2becd9c9e9118404545d19c4bd6c45d64ee3ecd4b6bafcefd97fbc",
199
- "tracks/A03 High Speed.scene.json": "b486b6b47cd36e609f5ec1be67d385e373df351c379c47193f8a0aba54c88924",
200
- "tracks/A03 High Speed.spawn.json": "7f8a9020b2aef433d876679262fc337928a4218cea3d2efa3ac6798b2eb122eb",
201
- "tracks/A03 High Speed.track": "0fb8666063a4ee503cb5ad453d3135d7aae00a030254c5538581e73e7b94325e",
202
- "tracks/A04 Dirt.saved.json": "5feac332a0b8e72fdbc5b9aa29f38750ba22b02ef809eaacb9f58daae54e1b64",
203
- "tracks/A04 Dirt.scene.json": "dd28eaccaf7d270ff2ce4ebe572bf69a61349e107d05dff9792ea2f2c793ccb1",
204
- "tracks/A04 Dirt.spawn.json": "28d8b916b84e3073c1ba5d0dff9c9a7d85c375858ac8c6818b1d6314847961fe",
205
- "tracks/A04 Dirt.track": "483adf3e712436d448bf1187c467649f93cc7812f60db43345d4d0e061daa752",
206
- "tracks/A05 Two Terrains.saved.json": "847f869d1d9f3e410043ccbf253d3def0725afa730c695b1519ef642cebab60c",
207
- "tracks/A05 Two Terrains.scene.json": "a1e767ed6ddfd1fdaabed07a13ca71beaa074c051cb9ce70ad6c476880562bf1",
208
- "tracks/A05 Two Terrains.spawn.json": "f8969c365d01c04a7a95b8abd5596618b70f52531eb03689ff908a27228056c3",
209
- "tracks/A05 Two Terrains.track": "3493c825514e7304110db828e5a0fc58cce18dfa1a2a118b50addb2d71d4ff08",
210
- "tracks/A06 Ice.saved.json": "97b93faa93ffea17dbac296c610228b5e452d0c1dfb14de30062e3e680d6cc1c",
211
- "tracks/A06 Ice.scene.json": "da6fce1651fbb318fcc312632feca8961dcf85a79b7e74813b2427e696c716a1",
212
- "tracks/A06 Ice.spawn.json": "b0f8af0dc885fc751eab1522da10592b5493bbc64843869e2426e1eca64e440d",
213
- "tracks/A06 Ice.track": "a9acc1478f1d48808b30077f94c8a55ed64027cd0aa4c65cf0a2e1718c524bd1",
214
- "tracks/A07 Three Terrains.saved.json": "a13bc4079a744791d2831aa971781bec349daedbe6bc104084741a561a637825",
215
- "tracks/A07 Three Terrains.scene.json": "2888b82fa94b84c3b679a7c0ce81b7b2ccaaac7756907c893f85aed17f1059b8",
216
- "tracks/A07 Three Terrains.spawn.json": "6e010816e7b8acd2401b89473fb22e9894cbfb88ec58060b47ae48e3091cbd21",
217
- "tracks/A07 Three Terrains.track": "c157d8246d250940b9601b7c87b6c4edeef1bd75b5bab9aa69427d76d95cc7e6",
218
- "tracks/A08 Long.saved.json": "99557126538ff8d2fac553262178427a91094eceaca39b32949141a310673113",
219
- "tracks/A08 Long.scene.json": "f02099b86907f7cad9696ccadd814c626c59da47550f00d53307a4da535774e0",
220
- "tracks/A08 Long.spawn.json": "6c082f62cb29b0a3cbc791b7531a4c9aeaf774f7e6dfa644f9ab40a2c3c6a815",
221
- "tracks/A08 Long.track": "ef34644dd6f9900bb76a41fbe759a183830b17b1b6eea7f19cab1ba43ea7d96e",
222
- "tracks/A09 Sharpest.saved.json": "8eae9b874f9b05050afa36370fa47f78b762ccba6d0d9665113b947a1a9e18d7",
223
- "tracks/A09 Sharpest.scene.json": "05d4907988d0b9343c1800c74d0b3d0ea3f13ecd96514426b2303a211a9610b4",
224
- "tracks/A09 Sharpest.spawn.json": "1027c03c0ef1bfd373e913c7dc77b256d0058e7b3b3cc6dc7d014a534019d972",
225
- "tracks/A09 Sharpest.track": "407106de14243819966ddf30cad20979d979f94a798e94551a31a5538b705b5d",
226
- "tracks/B01 Oval.saved.json": "0c42ed69583b7a6041837b10a4d2de7d4bcf4426ca91f657b5c1ce005a77f9b7",
227
- "tracks/B01 Oval.scene.json": "f90567dcbbf2e7ed4dd8e578c63efe2962bc8fa836692e6c8c9494f4788b05e8",
228
- "tracks/B01 Oval.spawn.json": "38bbe40879c18d9187eda23c9850c70f7762ea769b5d72208607b49bc2327c71",
229
- "tracks/B01 Oval.track": "b4152d06083e5c871ec356ceff917de1ef5f72d6e27b9618959125a5e41e5a8c",
230
- "tracks/B02 Snake.saved.json": "54c4f010a73e3549115ab9b160c9823d0f96fa920602507fcf251a9fd29619b4",
231
- "tracks/B02 Snake.scene.json": "5ed52574b620de959a0c2005c7fd371f6d2f29b5dc2f20e930b13e8d93fc0f4c",
232
- "tracks/B02 Snake.spawn.json": "2fb95139538ed66324e10750278ee250e8bc159ccab3d27320efc21de7601e5b",
233
- "tracks/B02 Snake.track": "fbd98acba4c3580b6e37cf72ed63b5b2e0477b86ce64320a8423449b59df7e0d",
234
- "tracks/B03 Slalom.saved.json": "6132213bdb3ece3f3ba1297200169aebd818fdff7e64ddc37d212c097322e9fc",
235
- "tracks/B03 Slalom.scene.json": "13acb54facddc61b033070621dc92bdcd82cc35deadfa811020b788f15c90b5c",
236
- "tracks/B03 Slalom.spawn.json": "f8969c365d01c04a7a95b8abd5596618b70f52531eb03689ff908a27228056c3",
237
- "tracks/B03 Slalom.track": "f0014f7d33fd982fdf56d3f5fcfbccf5470ae5b3735480d4bcc959f2d5e61707",
238
- "tracks/B04 Rally.saved.json": "1ba74c6c2e3dedddc9864379b6f824e8f32d45bd9cf566fcfdcf4074d633d817",
239
- "tracks/B04 Rally.scene.json": "b61381b0932d40bc99f422f550d5d04612b8902dafb48e6e99752de817f40c2e",
240
- "tracks/B04 Rally.spawn.json": "a864506108c968ab8e5949403825a387a9ab679aa3c97c2f85f51f593530cf17",
241
- "tracks/B04 Rally.track": "6e03ca93bbd59f6e1cb05e3382c7959cc09f3abb5d9f76e8a224dd7365a21844",
242
- "tracks/B05 Racetrack.saved.json": "d8fddedd268be9dda3e30f337663c3f1d42777c1cbcd6cb92055a8b50d154471",
243
- "tracks/B05 Racetrack.scene.json": "1b69b006af727c249097fe996bd280f2f66751d78463678045db4bdfa7b7ccda",
244
- "tracks/B05 Racetrack.spawn.json": "caf4e703eeef12f246e0456e9d4fecfd92020c86d6295813136c4dd68226aae9",
245
- "tracks/B05 Racetrack.track": "43cea4d2ffd3ca3bc19de5b662b67228f7a9a35adfccf1af84a17ade07b5124a",
246
- "tracks/B06 Hard.saved.json": "fe3bf789f34b9092b0c8486c80705f1aaeb38603d9a7263bbc2e4bf24fa0a7e6",
247
- "tracks/B06 Hard.scene.json": "18b7dadde263aac8316ddb4b10e8d28321b799bdd17acb4c69508281dbbe949b",
248
- "tracks/B06 Hard.spawn.json": "64cd8fd30bc1909522aaa0cf2df52bf980e6e4df2c5f3c4be173e4ecdd6881bb",
249
- "tracks/B06 Hard.track": "b45330b2a4ec12b6cc7a62ab403c5cd7b864aa3ca7ce698da9678d80fefd5277",
250
- "tracks/B07 Drift.saved.json": "549247a1c38d9f5462d416a2d3a00c3d032e8ca0358d75f2503bae9e277b3d79",
251
- "tracks/B07 Drift.scene.json": "d8e3bfeea412780ae10a46bfcfee216bec1241f70dcab408a8de3b26bb7abd65",
252
- "tracks/B07 Drift.spawn.json": "0c39c94ec48e01cde57873716585fc104b61d5bca9c3eff841342129d9b02078",
253
- "tracks/B07 Drift.track": "73e0f3b11458f16e99b5c67987253a0d2e31a8dddf93bbae95ccf2ef09f206a0",
254
- "tracks/B08 Arctic Circle.saved.json": "02b2be3a2c62083835f7fefe31788e666e523e4681b9c840ef6b8f2375b213d6",
255
- "tracks/B08 Arctic Circle.scene.json": "af5c3bbb39ba6c143244d604df0c8b68ad7d8ef2889299cca52ed53dbf2b0980",
256
- "tracks/B08 Arctic Circle.spawn.json": "ee1454cbec1c9b48ca0cf88e4337ada23a62827716a1ff10e1a480cace798043",
257
- "tracks/B08 Arctic Circle.track": "4ec9803238b933999c5a1a16f8718b7a6b12ebb2aa88615212b9caddef3cc154",
258
- "tracks/B09 Checkered.saved.json": "9c015b35fb7085c622852b27f30881e28c0c02aeb5c82cc24e069cd5b838b878",
259
- "tracks/B09 Checkered.scene.json": "1f8927da796828fde4b2f86bec1650a7896ab0cbf3855d59894b9c499e43c52d",
260
- "tracks/B09 Checkered.spawn.json": "cd6e0efcdf24be3ce06afbeaefa2c956085172612f73b2c773dfcc4220debd5b",
261
- "tracks/B09 Checkered.track": "a9df6dc6a7817eaab6d7233846e29ae44f826a9e035aa578ceaef386e12dcdd3",
262
- "tracks/R01 Blitzring.saved.json": "92741bab01c659d294d6e5ddcb09905655f681de170dd9b9c850bb2a50ddb19b",
263
- "tracks/R01 Blitzring.scene.json": "a2e6d19aadc4cc7e614f974c5db399e0ff0a105682e38a8fbfe6e9e4ece4686e",
264
- "tracks/R01 Blitzring.spawn.json": "7795cac05e10bfe8f16a0cb0ef5a93edf0df443085df22d81d8955a8fb39ab2d",
265
- "tracks/R01 Blitzring.track": "560aafb1ecb7fa07671cfaa79ea429e5db7c64ffa625f25a24fbb046732f13bc",
266
- "tracks/R02 Desert Rally.saved.json": "3f5e88bb2c3ea08ed933d529112b8e99cce6817cb19e1896ac7f3f478eb4256e",
267
- "tracks/R02 Desert Rally.scene.json": "3ae7ee8cb62758d5ac09004536dce9ce19b99b0d732459e1a753bdf433c28ef1",
268
- "tracks/R02 Desert Rally.spawn.json": "fc8dc10779bb6750039b84308aaeb8e5b046fffd07932f82c88eb17654cfbe9c",
269
- "tracks/R02 Desert Rally.track": "15269225ce25cc964e79783ba5833c9135f561a7ae7c482b1f1f402feb83aa67",
270
- "tracks/R03 Glacier.saved.json": "899727f504a4552522a66f65803498dbc535b943280ba2e41979018ed7a6d77f",
271
- "tracks/R03 Glacier.scene.json": "5926a121ab9fe5a37cda9037357ef27a53d1ba79c217a6ee1e8561bb199d23b7",
272
- "tracks/R03 Glacier.spawn.json": "ae91e75e037ba1d8b039a638860b6a93535d25e0804638dd1ec533296394e82f",
273
- "tracks/R03 Glacier.track": "93d85045b4af30be986fb1cf9e5a2462ed25f34dd17b1dc5bdebcc06f2f58f0c",
274
- "tracks/R04 Truck Maze.saved.json": "3a0de310132581c730acdf493dbd9d6506f9d78479e5cfe83c55f8f788f0895e",
275
- "tracks/R04 Truck Maze.scene.json": "6d0955f94394a2786601053aa6c3da3135457b470df069ae102e90238a96e295",
276
- "tracks/R04 Truck Maze.spawn.json": "6632d1b815145ef63173b33f740a8038ace886fc80d3d19d153dc0317e700b64",
277
- "tracks/R04 Truck Maze.track": "69f3b7813716bc408853f76368b9640a8b5fac60c0fe84bf68bb19f2f8cf5680",
278
- "tracks/R05 Endurance 500.saved.json": "b13fe6d518cf8754ca362f8b04e09e5f1b58c5255c113879645b01c09df5c09f",
279
- "tracks/R05 Endurance 500.scene.json": "3d61c23d726261d3d05f69561e80d21ae9335fe40d311953a9f1833b4130e4c1",
280
- "tracks/R05 Endurance 500.spawn.json": "4012030b01cb4fd551aa5944a442ad6ec13e5afa66804728a4df855854eee339",
281
- "tracks/R05 Endurance 500.track": "ab701400945b302b600270a3d510e6a3604a9ae29a3f7aa00df9628f7ecd9ac3",
282
- "tracks/R06 Mix.saved.json": "e897ba1f8697b137c4866ebb76b8a50b873cd1ec2d185cb86389b1e8e166341c",
283
- "tracks/R06 Mix.scene.json": "ead016d8e9ad39bb56f58d7456284321aef6d31f67684a5573845a5ac63a7c97",
284
- "tracks/R06 Mix.spawn.json": "c491511a8202b0bb4ba996c9f96a8d579dc30b443f5ff09984a18c5daee2ad89",
285
- "tracks/R06 Mix.track": "140d6aa9a0e4bfa1a6776ac05597bbcd7a75c073935426a74b540374312f9460",
286
- "tracks/R07 Mirage Marina.saved.json": "a87a65b016d8ae787ec60f928c55184615d7bdcae9417ccae728d2ed8284295f",
287
- "tracks/R07 Mirage Marina.scene.json": "6c9df3b4faf505605db29b48e4d86ca99c86ff6493859f93724b06ba8cfbf3cf",
288
- "tracks/R07 Mirage Marina.spawn.json": "5f60a1fa3a25211fa2a9b3b4320565001c65e7600c8de6bf1bf33206b1fe6a2d",
289
- "tracks/R07 Mirage Marina.track": "5eb0d06262c6e78dc00872591dec541780a1c9a0835ad608cea474f4b038d68f",
290
- "tracks/R08 Demolition Derby.saved.json": "f1d4f738570d6f4d3139839c1b1bec01f22f4fb43ac272d971df30960e7a7736",
291
- "tracks/R08 Demolition Derby.scene.json": "8526629ee38c06c7d10b490316aae5fde5be185c286678d7304bd5e0208bb743",
292
- "tracks/R08 Demolition Derby.spawn.json": "62cf46bf13fd9a3fb57a8891edcbd74af430174346bd5782f57796c18653a12c",
293
- "tracks/R08 Demolition Derby.track": "00816f68f620008cbe560a9098883834d5fb3eef664c37f00504c8fe9d025f0e",
294
- "tracks/R09 Eau Noir.saved.json": "be13d95668e41982fe0aac22a3a69df934fdbb57234e80c53c5ef9bbdfbd6f55",
295
- "tracks/R09 Eau Noir.scene.json": "e27ca05758a1ae98c7021f62d255745c1fd25350076ee9735131f4ce407a6a5e",
296
- "tracks/R09 Eau Noir.spawn.json": "045e758d23b577e4a44597e1fef831b8689253bb3cbae3ad6d4309f4a4d79359",
297
- "tracks/R09 Eau Noir.track": "ba77ee9396d44f13bf079ebcbbfb6aa6f44bae83fd8725b20eb559ac383ed79a",
298
- "tracks/The Champions Trial.saved.json": "ccb4b73d7c01c607ae7afc655c476d92d15809cfd7ac66c1750646368ddfa2f2",
299
- "tracks/The Champions Trial.scene.json": "5aead756212996a349023f4cfa2046ab0eced2a226777f9f32e27f9d533bf332",
300
- "tracks/The Champions Trial.spawn.json": "b0ffd429583ecc6806854b672c2cf683ea305f17a49800942c9242d4490a95da",
301
- "tracks/The Champions Trial.track": "27e612b7e5f4c0356a02c2d6ee0d0d03383543ce84dc36fc74a62a259e8493c3",
302
- "tracks/catalog.json": "a043d34c557d35871bbf3b9c5ba018e882158a53b7e55d9ee8eec9782efad7ce",
303
- "tracks/compatibility-receipt.json": "00948fe53db0995281e9a4593186d1322baaeaae0c41414b77724d8e59980122",
304
- "vendor/games/__init__.py": "f6701b872373bd606865daad0cb3d55c6815b78a6bdf1a780ac6fa99f53f0a3a",
305
- "vendor/games/ai_learns_to_drive/__init__.py": "53b2d4f6dac65249b79fd40331d2668f3d4ecf999616cf728912be39bf77431f",
306
- "vendor/games/ai_learns_to_drive/batched_controller.py": "f1386798ab6a74a095720003fc4a7dbb5e01ada6e114c130e558e8a54215d2c1",
307
- "vendor/games/ai_learns_to_drive/cli.py": "716d092b390dd205f2689c779f1a3a47b8c2dbd77597e01049ce4ba1d1f63856",
308
- "vendor/games/ai_learns_to_drive/collision.py": "6179d7581c1a2f42d8f028ab30e701dd11c3ecd125eec270fc73c256ae114a39",
309
- "vendor/games/ai_learns_to_drive/evolution.py": "adee47e38d62f1c9b7f303171552a7000f4c281384b03daa8410bf8c6fbd7fc7",
310
- "vendor/games/ai_learns_to_drive/evolutionary_trainer.py": "739d11b924f2232ae57570da5d9f6dd395f2a272a2ac9f2ea383b9646ab0420a",
311
- "vendor/games/ai_learns_to_drive/managed_math.py": "90d88e3376d8ec49b5913e26c6a5923d355a3aa303977d28ec74a027f690d59b",
312
- "vendor/games/ai_learns_to_drive/physics.py": "942abdf7dee4d9d5b0644decf6351e9f9d7956a8e7613e46575fa361da68d547",
313
- "vendor/games/ai_learns_to_drive/physics_profiles.py": "5e5dd4cf5ebc5be09c2180b0b69af9833b95e6a7e801da5cbd1b46f4527cddc9",
314
- "vendor/games/ai_learns_to_drive/presentation.py": "6ffc09d2ca5d1791d7147ec1fded6c94860d66b51c411441d16c9a93b5e095d3",
315
- "vendor/games/ai_learns_to_drive/provenance.py": "e739f162e3c863085b3fb960638f1d66a726456e2b4434a2e964c6b9888b8b2e",
316
- "vendor/games/ai_learns_to_drive/records.py": "b7c65c165adb814b75dabad5595a139220a1a549958990315a9d3659194b0345",
317
- "vendor/games/ai_learns_to_drive/reproduction.py": "02f096286d3f629f6a0feecf173dbcdfca4b7f898f07e55b853a490c5a953be9",
318
- "vendor/games/ai_learns_to_drive/rewards.py": "a9f2833ca923dcc5c51d35f802615559cbd7cf0c8468803d83c94ce3efbcf3de",
319
- "vendor/games/ai_learns_to_drive/runtime_cache.py": "b5d0f9e92cc15da25e5039b666733a7d7dd0d660b9db7516672945f2498ac846",
320
- "vendor/games/ai_learns_to_drive/scoring.py": "66038035a63d181c60a4a657f39ac38ebf72aab6e0d91432edbcdb46d1a03f6f",
321
- "vendor/games/ai_learns_to_drive/sensors.py": "77309aa3cbda26d521db81413cd2be8bee18f305358c9f849e346523efc9377c",
322
- "vendor/games/ai_learns_to_drive/sessions.py": "072a306ebb1c8286a875c1476f4e56a4de1b7468b6f168d0a7778407391c672d",
323
- "vendor/games/ai_learns_to_drive/settings.py": "b802210677437f0537e2902dd3fdbe72006a943e519f08ff53c7c2ee40383dc7",
324
- "vendor/games/ai_learns_to_drive/simulation.py": "30b69106673f62e8ced5e58077058941a75abda2865d704c2a4e715781d7e406",
325
- "vendor/games/ai_learns_to_drive/tracks.py": "24d8e098108d8be033da1292c9c72d2047935dd5dc1084fb2cdd24e6c55efa3d",
326
- "vendor/games/ai_learns_to_drive/trainer.py": "5e17bcc7bc594a4bc27223106313497112488f7e6bb6c75618239878426355cd",
327
- "vendor/reward_extraction.py": "69d10fb82594ec5f391ac6814f2677355a6448c5eb1a9d28a3c677333cdc6384"
328
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
README.md CHANGED
@@ -1,5 +1,5 @@
1
  ---
2
- title: AI Learns To Drive — TiGa interface
3
  sdk: gradio
4
  sdk_version: 6.29.1
5
  python_version: "3.10"
@@ -8,16 +8,8 @@ hf_oauth: true
8
  hf_oauth_expiration_minutes: 60
9
  ---
10
 
11
- Protected CPU/ZeroGPU integration candidate. Custom interface with Gradio Server on port 7860.
12
- Simulator: https://github.com/Zorro909/driving_sim_rs
13
- Hosting adaptation and UI: TiGa https://github.com/seeker-cyber-maker/driving_sim_rs
14
- CPU is the default; GPU requests explicitly use ZeroGPU. No automatic fallback. 28 built-in editor-format replica tracks; no bundled networks. See TRACK_LIBRARY.md for provenance and limitations.
15
- One server process; no persistent storage. See DATA_POLICY.md for retention limits.
16
- Not yet verified in the hosted Linux runtime; do not publish as a stable release.
17
 
18
- Expanded runner UI beta candidate: configurable training, settings-only browser
19
- recipes, bounded sequential batches, browser-local network creation/editing.
20
- Track rendering and star evaluation are not connected. This new package is
21
- not hosted-qualified. See BETA_TESTING.md and STORAGE_BOUNDARY.md.
22
 
23
- Optional HF OAuth: openid/profile only. CPU remains anonymous. Visitor tokens live in browser memory; queue identity is checked before GPU dispatch. No personal token entry, server session store, or automatic CPU fallback.
 
1
  ---
2
+ title: AI Learns To Drive — GPU lab
3
  sdk: gradio
4
  sdk_version: 6.29.1
5
  python_version: "3.10"
 
8
  hf_oauth_expiration_minutes: 60
9
  ---
10
 
11
+ Protected CPU/ZeroGPU training beta using Zorro909/driving_sim_rs at commit b90b8af06ffc4ea4e4fd703becd1107a48b8e5e0. Open the public app at https://tiga-rce-ald-tao-gpu.hf.space/; the source repository remains restricted. CPU runs anonymously. GPU is explicitly selected and subject to available HF allowance; optional HF sign-in uses the official OAuth flow and needs no personal token entry.
 
 
 
 
 
12
 
13
+ The selected track map previews tile layout and asphalt/dirt/ice directly from the selected file. Twenty-eight reconstructed editor-format tracks are included. Settings-only recipes and batches save in the visitor's browser. Formula steering/acceleration networks within the current worker limits are supported.
 
 
 
14
 
15
+ Application-controlled inputs and intermediate files are temporary. Outputs are held in memory for at most five minutes and deleted sooner after verified download by default; a single-run visitor may explicitly keep the result until that five-minute deadline. This is not a provider-wide zero-data-retention guarantee. Read DATA_POLICY.md and TRACK_LIBRARY.md. Upstream code and license: https://github.com/Zorro909/driving_sim_rs. Open upstream PRs 19 and 21 are not included.
RELEASE_MANIFEST.json CHANGED
@@ -1,21 +1,25 @@
1
  {
2
  "backend": "cpu+zerogpu",
3
  "files": {
4
- "BETA_TESTING.md": "d511965b9d675a092571f8815348da991ef1ef6be3766266c1f98ff393fd3a4d",
5
- "DATA_POLICY.md": "1434ac5420a611b35c69da90bbbb70abb088754fdab0354a51f0f892b4abe224",
6
- "FRONTEND_SOURCE.json": "35f4b3eb2e268d4fd11aa36feb1220267c683395e2e1b0bf2ff535a945ac16f8",
 
 
7
  "GODOT_LICENSE": "fb2b3bb82c60f1e76841ba2122eb902f8e39c151476fe21ce10c9a05d1045304",
8
  "IMPORTER_BUILD_RECEIPT.json": "4ba5c533cc617105478e4d85c83f456a7dfa68b1388049624619871ba9e42e9d",
9
  "LICENSE": "53d5851b6440feeae36f72a5f57fcab37858c48b7084765ece4b0c54b9a28ed8",
10
- "README.md": "5157c28039004afb7a6ef40a5f5bc27ba431f16efd7d1d2482e9bdf34373f8fe",
11
- "STORAGE_BOUNDARY.md": "cf6f4b6824f0780766a5c3a44e372e6e9b1cf7d73428cc14770af7ed5ade5d45",
12
  "TRACK_LIBRARY.md": "7e4829c5e0933bfb317c21d7441ad0ba2ee00ab7f9f1635549452d504aa0777b",
 
13
  "app.py": "704f789a41846b0a5bc1d3f6f5305d7ac5a6b1719ff77c23585b89fd3e68d55d",
14
  "app_release.py": "7482559c667a665fd3cb6aa8af6c78422a822b515e14589db8306f7fd4860a8b",
15
  "assets/formula_template.json": "80f745df82bb7be45af52785fd582460bcddc63c5a4e1d8375d85b3122db4c6b",
16
- "bin/altd-sim": "2f2f2144ae14b0ef599ca8510f95712da00243c6875881491d384b394e7499f7",
 
17
  "bin/extract_saved_track": "3a7733c45b4301a786fcbfe92660a1c484749272da5f608d62f34878bd4ff31a",
18
- "bin/libaltd_gpu.so": "279d6353b4c691686d6aeeae6abfd4a82b959e9b604f079a6c45f9823b48a87a",
19
  "builtin_tracks.py": "2ecc2b1d00fe15701b0271d71e1e68d2e7e59c596330879494055f9b2a99c242",
20
  "builtin_tracks/catalog.json": "65006e70a87a5a53e3738166b0895bc4db9f99767dd891d917b68029abb4e80a",
21
  "builtin_tracks/tracks/Replica A01 Beginner.track": "ca5749537450430794e2eade2e0ac72fa141a4f225e13e2f8ef842abb948ff15",
@@ -46,15 +50,16 @@
46
  "builtin_tracks/tracks/Replica R08 Demolition Derby.track": "6f11a9ffbcb477c9d19964566b1b612d2a94675605246e93e21f27bbbdb357ef",
47
  "builtin_tracks/tracks/Replica R09 Eau Noir.track": "3ec0a78478cca1a4f0d2d98ac81f40783928adf271b70f0c32d295a6da2cdaa9",
48
  "builtin_tracks/tracks/Replica The Champions Trial.track": "a3bfb76422affc774b44c739b0636d08acb901fa7615b9adcb52c069f79834e1",
49
- "client.js": "628ca4edec49c45302bbcbbc7c35f640442a7670105cdb42d8e21c59f1db1ff2",
50
- "delivery.py": "4f5a4e45df92e5cbfdef6eb449ede9ba26217fe24da376fafddae5cbbb73847a",
51
  "gpu_tickets.py": "c32cb5de751d49d3e1cd970c7d6328a42ebe71602dd9fd3788c872eef42611da",
52
  "hf-auth.js": "b59691ce2c517f193a5d5141538ebe61c961bb163cefa1fcf09b414c388984c1",
53
  "hf_identity.py": "6993d0238ada835606dbdc3275c17a3fe5a5cac5ad2156ab78230acf2d051eba",
54
- "index.html": "24fd848cd38d84d84236558e1d617d79554ae462317b3bea68b11c74d2802076",
55
  "requirements.txt": "9b532747e51bd052e82090ece860d6dafe027407f4512dc74272c148ea104c22",
56
- "server.py": "dd9d2e709ea61b6a3e3942be8377f0cad12509d4df3dbe0baa930523c0a3120c",
57
- "track-library.js": "d19e2a58442e07d0d5029fbdfae1461106b2c3fe91dcb7b3091e304fc700811a",
 
58
  "training_config.py": "2b9768876fdc60b16afb45b98023c6c31666e30f7c56f1292f6071775e6da0c5",
59
  "vendor/gradio-client/LICENSE": "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4",
60
  "vendor/gradio-client/dist/index.min.js": "fdd776db8633354f118fe2908c980592283968737e6b91dc3aa86d648da5c3fd",
@@ -64,7 +69,6 @@
64
  "vendor/hf-oauth/package.json": "fafd4d8891023a1961546a7d3bc25cd24f64923a2ebfc449fe6d516a2949bda8",
65
  "worker.py": "934fb941a7f73a82c9bbcff5f3290103d4dd55e66542e71d56ae8fe7101f0e57"
66
  },
67
- "hosted_verified": false,
68
- "interface": "runner-beta",
69
- "upstream_revision": "d8ab74c25df70b6a86ed101080e33d5fb785ea6f"
70
  }
 
1
  {
2
  "backend": "cpu+zerogpu",
3
  "files": {
4
+ ".gitattributes": "c2ad16718fc51c888d32efc88c8f6e23ebe5fcf6f48e2954f896ba9770f24d72",
5
+ "BETA_TESTING.md": "b3c8ca006e67bea3511a9e3e8cc976991a57a14fed93085739842d5e312818b4",
6
+ "BINARY_PROVENANCE.json": "02760a067747114299a6b79c3de2cd88e42395f43c37ce34c0b1678d6c445524",
7
+ "DATA_POLICY.md": "aaf42a8d3f2b82f4410fa2477bd5c09779c265baadda41ce567ad44bd23fea73",
8
+ "FRONTEND_SOURCE.json": "0b9d9983a6feb93ae56ea95c037d7f744ade111824617785a0cd9f7e2f61308e",
9
  "GODOT_LICENSE": "fb2b3bb82c60f1e76841ba2122eb902f8e39c151476fe21ce10c9a05d1045304",
10
  "IMPORTER_BUILD_RECEIPT.json": "4ba5c533cc617105478e4d85c83f456a7dfa68b1388049624619871ba9e42e9d",
11
  "LICENSE": "53d5851b6440feeae36f72a5f57fcab37858c48b7084765ece4b0c54b9a28ed8",
12
+ "README.md": "478d7eef40681c0657a0e03628576ea275f7db197974de62ee8ed3f20bf2c8f4",
13
+ "STORAGE_BOUNDARY.md": "0cda17053a343c2c83055e5a7e1191f1567199622a6eea422b48e11ec70e702e",
14
  "TRACK_LIBRARY.md": "7e4829c5e0933bfb317c21d7441ad0ba2ee00ab7f9f1635549452d504aa0777b",
15
+ "UPSTREAM.json": "f613a978cab5fe7824b26c620c784c38711a984cf2ecc4490ac8229e01957c55",
16
  "app.py": "704f789a41846b0a5bc1d3f6f5305d7ac5a6b1719ff77c23585b89fd3e68d55d",
17
  "app_release.py": "7482559c667a665fd3cb6aa8af6c78422a822b515e14589db8306f7fd4860a8b",
18
  "assets/formula_template.json": "80f745df82bb7be45af52785fd582460bcddc63c5a4e1d8375d85b3122db4c6b",
19
+ "assets/track-atlas.json": "d97c8900e3e5fb17734b5bd61d1f4f4b196d9be30af9848e2e273ae7e4079ae4",
20
+ "bin/altd-sim": "0135ecc3d435a9d327be7a92e048cfb5c5291a02ef1e0dddd6ead1cc19b31166",
21
  "bin/extract_saved_track": "3a7733c45b4301a786fcbfe92660a1c484749272da5f608d62f34878bd4ff31a",
22
+ "bin/libaltd_gpu.so": "0064e747543251bab90cb966f8df00b010716a92cc75910229d42c9b24c1dac9",
23
  "builtin_tracks.py": "2ecc2b1d00fe15701b0271d71e1e68d2e7e59c596330879494055f9b2a99c242",
24
  "builtin_tracks/catalog.json": "65006e70a87a5a53e3738166b0895bc4db9f99767dd891d917b68029abb4e80a",
25
  "builtin_tracks/tracks/Replica A01 Beginner.track": "ca5749537450430794e2eade2e0ac72fa141a4f225e13e2f8ef842abb948ff15",
 
50
  "builtin_tracks/tracks/Replica R08 Demolition Derby.track": "6f11a9ffbcb477c9d19964566b1b612d2a94675605246e93e21f27bbbdb357ef",
51
  "builtin_tracks/tracks/Replica R09 Eau Noir.track": "3ec0a78478cca1a4f0d2d98ac81f40783928adf271b70f0c32d295a6da2cdaa9",
52
  "builtin_tracks/tracks/Replica The Champions Trial.track": "a3bfb76422affc774b44c739b0636d08acb901fa7615b9adcb52c069f79834e1",
53
+ "client.js": "90a682cf27f4b8abc2de792fa90f6a32d859ca9918b7e92386b2c4d9366dd638",
54
+ "delivery.py": "07453999c3831a16e8b1fcc2b4ae5fb28beb7d3952a3fae8de65d16eb6f11e5b",
55
  "gpu_tickets.py": "c32cb5de751d49d3e1cd970c7d6328a42ebe71602dd9fd3788c872eef42611da",
56
  "hf-auth.js": "b59691ce2c517f193a5d5141538ebe61c961bb163cefa1fcf09b414c388984c1",
57
  "hf_identity.py": "6993d0238ada835606dbdc3275c17a3fe5a5cac5ad2156ab78230acf2d051eba",
58
+ "index.html": "d329965febb49db4939093ec0c512474db109a7b3a24e97cbabb18f97674757b",
59
  "requirements.txt": "9b532747e51bd052e82090ece860d6dafe027407f4512dc74272c148ea104c22",
60
+ "server.py": "44eee069364f1a5d952ed316d30e27908111394ce53d776ccf0fb8099c6aee81",
61
+ "track-library.js": "351ec4c026b49420ce963f4310cb000d9e987fd28e6dac5ecd0176509340f6e6",
62
+ "track-map.js": "ebf0ffe889983b677060c785edd6398afb53c9e680e1ea7f13614a6a16712ac7",
63
  "training_config.py": "2b9768876fdc60b16afb45b98023c6c31666e30f7c56f1292f6071775e6da0c5",
64
  "vendor/gradio-client/LICENSE": "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4",
65
  "vendor/gradio-client/dist/index.min.js": "fdd776db8633354f118fe2908c980592283968737e6b91dc3aa86d648da5c3fd",
 
69
  "vendor/hf-oauth/package.json": "fafd4d8891023a1961546a7d3bc25cd24f64923a2ebfc449fe6d516a2949bda8",
70
  "worker.py": "934fb941a7f73a82c9bbcff5f3290103d4dd55e66542e71d56ae8fe7101f0e57"
71
  },
72
+ "interface": "single-engine-runner-with-map",
73
+ "upstream_revision": "b90b8af06ffc4ea4e4fd703becd1107a48b8e5e0"
 
74
  }
STORAGE_BOUNDARY.md CHANGED
@@ -11,7 +11,7 @@ same settings contract is used independently of the selected storage policy.
11
  | Selected built-in track | Synchronized selectors and one verified Blob | Page memory across runs; no cookie, recipe or localStorage persistence |
12
  | Worker inputs / intermediate files | Temporary directory | Removed before successful result publication |
13
  | GPU pending inputs | Opaque single-use ticket plus memory store | Dispatch, fixed 120-second expiry, or shutdown |
14
- | Single-run output | Memory result store and random job key | Receipt ACK in automatic mode, manual delete, fixed 30-minute expiry, or shutdown |
15
  | Batch intermediates | Same job contract, always automatic | Verified size/hash and deletion ACK before advancement |
16
  | Received candidate / receipt | Browser page memory | Explicit discard, replacement, page reload/close; explicit export to disk |
17
  | Optional HF identity / token | Browser page memory, separate from job/recipe storage | Sign out, expiry, or page reload/close; no app auth cookie or server session database |
 
11
  | Selected built-in track | Synchronized selectors and one verified Blob | Page memory across runs; no cookie, recipe or localStorage persistence |
12
  | Worker inputs / intermediate files | Temporary directory | Removed before successful result publication |
13
  | GPU pending inputs | Opaque single-use ticket plus memory store | Dispatch, fixed 120-second expiry, or shutdown |
14
+ | Single-run output | Memory result store and random job key | Default receipt ACK; opt-in repeat download until fixed five-minute expiry; manual delete or shutdown |
15
  | Batch intermediates | Same job contract, always automatic | Verified size/hash and deletion ACK before advancement |
16
  | Received candidate / receipt | Browser page memory | Explicit discard, replacement, page reload/close; explicit export to disk |
17
  | Optional HF identity / token | Browser page memory, separate from job/recipe storage | Sign out, expiry, or page reload/close; no app auth cookie or server session database |
UPSTREAM.json CHANGED
@@ -1,10 +1,9 @@
1
  {
2
  "repository": "https://github.com/Zorro909/driving_sim_rs",
3
- "commit": "d8ab74c25df70b6a86ed101080e33d5fb785ea6f",
4
- "previous_space_commit": "a3b395b0b608fb7caa2081348be153feabc38a69",
5
  "math_profile": "proton",
6
  "role": "gpu",
7
- "gpu_runtime_verified": false,
8
  "open_prs_not_included": [
9
  19,
10
  21
 
1
  {
2
  "repository": "https://github.com/Zorro909/driving_sim_rs",
3
+ "commit": "b90b8af06ffc4ea4e4fd703becd1107a48b8e5e0",
4
+ "github_actions_run": 38203558700,
5
  "math_profile": "proton",
6
  "role": "gpu",
 
7
  "open_prs_not_included": [
8
  19,
9
  21
ZEROGPU_MANIFEST.json DELETED
@@ -1,10 +0,0 @@
1
- {
2
- "README.md": "cd5ad5b4e2dd5230ecc0eb3083ea40e90c3665b5a9529a4286fbead2ed37bacb",
3
- "app.py": "5d7e2fe152b0846f73a8383ef9e87c60925b4f7384221a4b04f639c5bdeb1e81",
4
- "probe_core.py": "97a36ad8cf8efec09d84bb4b2c1ee6794658ceedfd643cd9849ff3c6d85aca9d",
5
- "requirements.txt": "d4a97517b799a94b3370ea2e11aee3e41304aa12b77bab9abecd0b37e961acaf",
6
- "BINARY_PROVENANCE.json": "f2223c1c6e2bbf8f6101b46e11563f4d866f99094c529cd5584f3228309e6551",
7
- "bin/altd-sim": "2f2f2144ae14b0ef599ca8510f95712da00243c6875881491d384b394e7499f7",
8
- "bin/libaltd_gpu.so": "279d6353b4c691686d6aeeae6abfd4a82b959e9b604f079a6c45f9823b48a87a",
9
- "training_smoke.py": "91e278b8fdf1a025d2ce455f5a4e55b1751691be2689fadda92955fc6dcbb508"
10
- }
 
 
 
 
 
 
 
 
 
 
 
assets/track-atlas.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"blocks":{"101:0":{"connections":[{"index":1,"side":2,"type":0},{"index":0,"side":0,"type":0}],"surface":1},"101:1":{"connections":[{"index":2,"side":0,"type":0},{"index":1,"side":3,"type":0}],"surface":1},"101:2":{"connections":[{"index":1,"side":2,"type":0},{"index":0,"side":1,"type":0}],"surface":1},"101:3":{"connections":[{"index":0,"side":2,"type":0},{"index":1,"side":0,"type":0}],"surface":1},"101:4":{"connections":[{"index":1,"side":3,"type":0},{"index":2,"side":1,"type":0}],"surface":1},"101:5":{"connections":[{"index":2,"side":2,"type":0},{"index":1,"side":1,"type":0}],"surface":1},"101:6":{"connections":[{"index":1,"side":0,"type":0},{"index":0,"side":3,"type":0}],"surface":1},"101:7":{"connections":[{"index":1,"side":1,"type":0},{"index":2,"side":3,"type":0}],"surface":1},"102:0":{"connections":[{"index":1,"side":2,"type":0},{"index":1,"side":0,"type":0}],"surface":1},"102:1":{"connections":[{"index":1,"side":0,"type":0},{"index":1,"side":3,"type":0}],"surface":1},"102:2":{"connections":[{"index":1,"side":2,"type":0},{"index":1,"side":1,"type":0}],"surface":1},"102:3":{"connections":[{"index":1,"side":1,"type":0},{"index":1,"side":3,"type":0}],"surface":1},"103:0":{"connections":[{"index":0,"side":2,"type":0},{"index":0,"side":0,"type":0}],"surface":1},"103:1":{"connections":[{"index":2,"side":0,"type":0},{"index":0,"side":3,"type":0}],"surface":1},"103:2":{"connections":[{"index":2,"side":1,"type":0},{"index":2,"side":3,"type":0}],"surface":1},"103:3":{"connections":[{"index":2,"side":2,"type":0},{"index":0,"side":1,"type":0}],"surface":1},"104:0":{"connections":[{"index":1,"side":2,"type":0},{"index":2,"side":0,"type":0}],"surface":1},"104:1":{"connections":[{"index":0,"side":0,"type":0},{"index":1,"side":3,"type":0}],"surface":1},"104:2":{"connections":[{"index":1,"side":2,"type":0},{"index":2,"side":1,"type":0}],"surface":1},"104:3":{"connections":[{"index":1,"side":0,"type":0},{"index":2,"side":2,"type":0}],"surface":1},"104:4":{"connections":[{"index":0,"side":1,"type":0},{"index":1,"side":3,"type":0}],"surface":1},"104:5":{"connections":[{"index":0,"side":2,"type":0},{"index":1,"side":1,"type":0}],"surface":1},"104:6":{"connections":[{"index":1,"side":0,"type":0},{"index":2,"side":3,"type":0}],"surface":1},"104:7":{"connections":[{"index":1,"side":1,"type":0},{"index":0,"side":3,"type":0}],"surface":1},"105:0":{"connections":[{"index":1,"side":2,"type":0},{"index":1,"side":3,"type":0}],"surface":1},"105:1":{"connections":[{"index":1,"side":0,"type":0},{"index":1,"side":1,"type":0}],"surface":1},"106:0":{"connections":[{"index":1,"side":2,"type":0},{"index":0,"side":3,"type":0}],"surface":1},"106:1":{"connections":[{"index":0,"side":2,"type":0},{"index":1,"side":3,"type":0}],"surface":1},"106:2":{"connections":[{"index":1,"side":2,"type":0},{"index":2,"side":3,"type":0}],"surface":1},"106:3":{"connections":[{"index":1,"side":0,"type":0},{"index":0,"side":1,"type":0}],"surface":1},"106:4":{"connections":[{"index":2,"side":2,"type":0},{"index":1,"side":3,"type":0}],"surface":1},"106:5":{"connections":[{"index":0,"side":0,"type":0},{"index":1,"side":1,"type":0}],"surface":1},"106:6":{"connections":[{"index":1,"side":0,"type":0},{"index":2,"side":1,"type":0}],"surface":1},"106:7":{"connections":[{"index":1,"side":1,"type":0},{"index":2,"side":0,"type":0}],"surface":1},"107:0":{"connections":[{"index":0,"side":2,"type":0},{"index":0,"side":1,"type":0}],"surface":1},"107:1":{"connections":[{"index":0,"side":3,"type":0},{"index":2,"side":1,"type":0}],"surface":1},"107:2":{"connections":[{"index":0,"side":0,"type":0},{"index":2,"side":2,"type":0}],"surface":1},"107:3":{"connections":[{"index":0,"side":0,"type":0},{"index":0,"side":3,"type":0}],"surface":1},"107:4":{"connections":[{"index":2,"side":0,"type":0},{"index":2,"side":3,"type":0}],"surface":1},"107:5":{"connections":[{"index":0,"side":1,"type":0},{"index":2,"side":3,"type":0}],"surface":1},"107:6":{"connections":[{"index":0,"side":2,"type":0},{"index":2,"side":0,"type":0}],"surface":1},"107:7":{"connections":[{"index":2,"side":2,"type":0},{"index":2,"side":1,"type":0}],"surface":1},"108:0":{"connections":[{"index":0,"side":2,"type":0},{"index":2,"side":1,"type":0}],"surface":1},"108:1":{"connections":[{"index":2,"side":2,"type":0},{"index":2,"side":0,"type":0}],"surface":1},"108:2":{"connections":[{"index":0,"side":0,"type":0},{"index":2,"side":3,"type":0}],"surface":1},"108:3":{"connections":[{"index":0,"side":1,"type":0},{"index":0,"side":3,"type":0}],"surface":1},"109:0":{"connections":[{"index":0,"side":2,"type":0},{"index":2,"side":3,"type":0}],"surface":1},"109:1":{"connections":[{"index":2,"side":2,"type":0},{"index":0,"side":3,"type":0}],"surface":1},"109:2":{"connections":[{"index":0,"side":1,"type":0},{"index":2,"side":0,"type":0}],"surface":1},"109:3":{"connections":[{"index":0,"side":0,"type":0},{"index":2,"side":1,"type":0}],"surface":1},"10:0":{"connections":[{"index":0,"side":2,"type":0},{"index":0,"side":3,"type":0}],"surface":0},"10:1":{"connections":[{"index":2,"side":2,"type":0},{"index":2,"side":3,"type":0}],"surface":0},"10:2":{"connections":[{"index":0,"side":0,"type":0},{"index":0,"side":1,"type":0}],"surface":0},"10:3":{"connections":[{"index":2,"side":0,"type":0},{"index":2,"side":1,"type":0}],"surface":0},"110:0":{"connections":[{"index":0,"side":2,"type":0},{"index":0,"side":3,"type":0}],"surface":1},"110:1":{"connections":[{"index":2,"side":2,"type":0},{"index":2,"side":3,"type":0}],"surface":1},"110:2":{"connections":[{"index":0,"side":0,"type":0},{"index":0,"side":1,"type":0}],"surface":1},"110:3":{"connections":[{"index":2,"side":0,"type":0},{"index":2,"side":1,"type":0}],"surface":1},"111:0":{"connections":[{"index":1,"side":2,"type":0},{"index":1,"side":3,"type":0}],"surface":1},"111:1":{"connections":[{"index":1,"side":0,"type":0},{"index":1,"side":1,"type":0}],"surface":1},"112:0":{"connections":[{"index":1,"side":2,"type":2},{"index":1,"side":3,"type":2}],"surface":1},"112:1":{"connections":[{"index":1,"side":0,"type":2},{"index":1,"side":1,"type":2}],"surface":1},"113:0":{"connections":[{"index":1,"side":2,"type":0},{"index":1,"side":3,"type":2}],"surface":1},"113:1":{"connections":[{"index":1,"side":0,"type":0},{"index":1,"side":1,"type":2}],"surface":1},"113:2":{"connections":[{"index":1,"side":2,"type":2},{"index":1,"side":3,"type":0}],"surface":1},"113:3":{"connections":[{"index":1,"side":0,"type":2},{"index":1,"side":1,"type":0}],"surface":1},"114:0":{"connections":[{"index":1,"side":2,"type":0},{"index":1,"side":3,"type":0}],"surface":1},"114:1":{"connections":[{"index":1,"side":0,"type":0},{"index":1,"side":1,"type":0}],"surface":1},"115:0":{"connections":[{"index":1,"side":2,"type":0},{"index":1,"side":3,"type":0}],"surface":1},"115:1":{"connections":[{"index":1,"side":0,"type":0},{"index":1,"side":1,"type":0}],"surface":1},"116:0":{"connections":[{"index":1,"side":2,"type":0},{"index":1,"side":3,"type":0}],"surface":1},"116:1":{"connections":[{"index":1,"side":0,"type":0},{"index":1,"side":1,"type":0}],"surface":1},"117:0":{"connections":[{"index":1,"side":2,"type":0},{"index":1,"side":3,"type":0}],"surface":1},"117:1":{"connections":[{"index":1,"side":0,"type":0},{"index":1,"side":1,"type":0}],"surface":1},"118:0":{"connections":[{"index":0,"side":2,"type":0},{"index":0,"side":3,"type":0}],"surface":1},"118:1":{"connections":[{"index":2,"side":2,"type":0},{"index":2,"side":3,"type":0}],"surface":1},"118:2":{"connections":[{"index":0,"side":0,"type":0},{"index":0,"side":1,"type":0}],"surface":1},"118:3":{"connections":[{"index":2,"side":0,"type":0},{"index":2,"side":1,"type":0}],"surface":1},"119:0":{"connections":[{"index":0,"side":2,"type":0},{"index":0,"side":3,"type":0}],"surface":1},"119:1":{"connections":[{"index":2,"side":2,"type":0},{"index":2,"side":3,"type":0}],"surface":1},"119:2":{"connections":[{"index":0,"side":0,"type":0},{"index":0,"side":1,"type":0}],"surface":1},"119:3":{"connections":[{"index":2,"side":0,"type":0},{"index":2,"side":1,"type":0}],"surface":1},"11:0":{"connections":[{"index":1,"side":2,"type":0},{"index":1,"side":3,"type":0}],"surface":0},"11:1":{"connections":[{"index":1,"side":0,"type":0},{"index":1,"side":1,"type":0}],"surface":0},"120:0":{"connections":[{"index":0,"side":2,"type":0},{"index":0,"side":3,"type":0}],"surface":1},"120:1":{"connections":[{"index":2,"side":2,"type":0},{"index":2,"side":3,"type":0}],"surface":1},"120:2":{"connections":[{"index":0,"side":0,"type":0},{"index":0,"side":1,"type":0}],"surface":1},"120:3":{"connections":[{"index":2,"side":0,"type":0},{"index":2,"side":1,"type":0}],"surface":1},"121:0":{"connections":[{"index":1,"side":1,"type":1},{"index":1,"side":3,"type":0}],"surface":1},"121:1":{"connections":[{"index":1,"side":2,"type":1},{"index":1,"side":1,"type":0}],"surface":1},"121:2":{"connections":[{"index":1,"side":0,"type":1},{"index":1,"side":2,"type":0}],"surface":1},"121:3":{"connections":[{"index":1,"side":3,"type":1},{"index":1,"side":0,"type":0}],"surface":1},"121:4":{"connections":[{"index":1,"side":0,"type":1},{"index":1,"side":3,"type":0}],"surface":1},"121:5":{"connections":[{"index":1,"side":2,"type":1},{"index":1,"side":0,"type":0}],"surface":1},"121:6":{"connections":[{"index":1,"side":1,"type":1},{"index":1,"side":2,"type":0}],"surface":1},"121:7":{"connections":[{"index":1,"side":3,"type":1},{"index":1,"side":1,"type":0}],"surface":1},"122:0":{"connections":[{"index":1,"side":2,"type":1},{"index":1,"side":0,"type":1}],"surface":1},"122:1":{"connections":[{"index":1,"side":0,"type":1},{"index":1,"side":3,"type":1}],"surface":1},"122:2":{"connections":[{"index":1,"side":1,"type":1},{"index":1,"side":2,"type":1}],"surface":1},"122:3":{"connections":[{"index":1,"side":3,"type":1},{"index":1,"side":1,"type":1}],"surface":1},"123:0":{"connections":[{"index":0,"side":2,"type":0},{"index":0,"side":3,"type":0}],"surface":1},"123:1":{"connections":[{"index":2,"side":2,"type":0},{"index":2,"side":3,"type":0}],"surface":1},"123:2":{"connections":[{"index":0,"side":0,"type":0},{"index":0,"side":1,"type":0}],"surface":1},"123:3":{"connections":[{"index":2,"side":0,"type":0},{"index":2,"side":1,"type":0}],"surface":1},"124:0":{"connections":[{"index":1,"side":2,"type":4},{"index":0,"side":0,"type":3}],"surface":1},"124:1":{"connections":[{"index":2,"side":0,"type":3},{"index":1,"side":3,"type":4}],"surface":1},"124:2":{"connections":[{"index":1,"side":2,"type":4},{"index":0,"side":1,"type":3}],"surface":1},"124:3":{"connections":[{"index":0,"side":2,"type":3},{"index":1,"side":0,"type":4}],"surface":1},"124:4":{"connections":[{"index":1,"side":3,"type":4},{"index":2,"side":1,"type":3}],"surface":1},"124:5":{"connections":[{"index":2,"side":2,"type":3},{"index":1,"side":1,"type":4}],"surface":1},"124:6":{"connections":[{"index":1,"side":0,"type":4},{"index":0,"side":3,"type":3}],"surface":1},"124:7":{"connections":[{"index":1,"side":1,"type":4},{"index":2,"side":3,"type":3}],"surface":1},"125:0":{"connections":[{"index":1,"side":2,"type":4},{"index":0,"side":0,"type":0}],"surface":1},"125:1":{"connections":[{"index":2,"side":0,"type":0},{"index":1,"side":3,"type":4}],"surface":1},"125:2":{"connections":[{"index":1,"side":2,"type":4},{"index":0,"side":1,"type":0}],"surface":1},"125:3":{"connections":[{"index":0,"side":2,"type":0},{"index":1,"side":0,"type":4}],"surface":1},"125:4":{"connections":[{"index":1,"side":3,"type":4},{"index":2,"side":1,"type":0}],"surface":1},"125:5":{"connections":[{"index":2,"side":2,"type":0},{"index":1,"side":1,"type":4}],"surface":1},"125:6":{"connections":[{"index":1,"side":0,"type":4},{"index":0,"side":3,"type":0}],"surface":1},"125:7":{"connections":[{"index":1,"side":1,"type":4},{"index":2,"side":3,"type":0}],"surface":1},"126:0":{"connections":[{"index":1,"side":2,"type":3},{"index":0,"side":3,"type":3}],"surface":1},"126:1":{"connections":[{"index":0,"side":2,"type":3},{"index":1,"side":3,"type":3}],"surface":1},"126:2":{"connections":[{"index":1,"side":2,"type":3},{"index":2,"side":3,"type":3}],"surface":1},"126:3":{"connections":[{"index":1,"side":0,"type":3},{"index":0,"side":1,"type":3}],"surface":1},"126:4":{"connections":[{"index":2,"side":2,"type":3},{"index":1,"side":3,"type":3}],"surface":1},"126:5":{"connections":[{"index":0,"side":0,"type":3},{"index":1,"side":1,"type":3}],"surface":1},"126:6":{"connections":[{"index":1,"side":0,"type":3},{"index":2,"side":1,"type":3}],"surface":1},"126:7":{"connections":[{"index":1,"side":1,"type":3},{"index":2,"side":0,"type":3}],"surface":1},"127:0":{"connections":[{"index":1,"side":2,"type":0},{"index":0,"side":3,"type":3}],"surface":1},"127:1":{"connections":[{"index":0,"side":2,"type":3},{"index":1,"side":3,"type":0}],"surface":1},"127:2":{"connections":[{"index":1,"side":2,"type":0},{"index":2,"side":3,"type":3}],"surface":1},"127:3":{"connections":[{"index":1,"side":0,"type":0},{"index":0,"side":1,"type":3}],"surface":1},"127:4":{"connections":[{"index":2,"side":2,"type":3},{"index":1,"side":3,"type":0}],"surface":1},"127:5":{"connections":[{"index":0,"side":0,"type":3},{"index":1,"side":1,"type":0}],"surface":1},"127:6":{"connections":[{"index":1,"side":0,"type":0},{"index":2,"side":1,"type":3}],"surface":1},"127:7":{"connections":[{"index":1,"side":1,"type":0},{"index":2,"side":0,"type":3}],"surface":1},"128:0":{"connections":[{"index":1,"side":2,"type":3},{"index":0,"side":3,"type":0}],"surface":1},"128:1":{"connections":[{"index":0,"side":2,"type":0},{"index":1,"side":3,"type":3}],"surface":1},"128:2":{"connections":[{"index":1,"side":2,"type":3},{"index":2,"side":3,"type":0}],"surface":1},"128:3":{"connections":[{"index":1,"side":0,"type":3},{"index":0,"side":1,"type":0}],"surface":1},"128:4":{"connections":[{"index":2,"side":2,"type":0},{"index":1,"side":3,"type":3}],"surface":1},"128:5":{"connections":[{"index":0,"side":0,"type":0},{"index":1,"side":1,"type":3}],"surface":1},"128:6":{"connections":[{"index":1,"side":0,"type":3},{"index":2,"side":1,"type":0}],"surface":1},"128:7":{"connections":[{"index":1,"side":1,"type":3},{"index":2,"side":0,"type":0}],"surface":1},"12:0":{"connections":[{"index":1,"side":2,"type":2},{"index":1,"side":3,"type":2}],"surface":0},"12:1":{"connections":[{"index":1,"side":0,"type":2},{"index":1,"side":1,"type":2}],"surface":0},"13:0":{"connections":[{"index":1,"side":2,"type":0},{"index":1,"side":3,"type":2}],"surface":0},"13:1":{"connections":[{"index":1,"side":0,"type":0},{"index":1,"side":1,"type":2}],"surface":0},"13:2":{"connections":[{"index":1,"side":2,"type":2},{"index":1,"side":3,"type":0}],"surface":0},"13:3":{"connections":[{"index":1,"side":0,"type":2},{"index":1,"side":1,"type":0}],"surface":0},"14:0":{"connections":[{"index":1,"side":2,"type":0},{"index":1,"side":3,"type":0}],"surface":0},"14:1":{"connections":[{"index":1,"side":0,"type":0},{"index":1,"side":1,"type":0}],"surface":0},"15:0":{"connections":[{"index":1,"side":2,"type":0},{"index":1,"side":3,"type":0}],"surface":0},"15:1":{"connections":[{"index":1,"side":0,"type":0},{"index":1,"side":1,"type":0}],"surface":0},"16:0":{"connections":[{"index":1,"side":2,"type":0},{"index":1,"side":3,"type":0}],"surface":0},"16:1":{"connections":[{"index":1,"side":0,"type":0},{"index":1,"side":1,"type":0}],"surface":0},"17:0":{"connections":[{"index":1,"side":2,"type":0},{"index":1,"side":3,"type":0}],"surface":0},"17:1":{"connections":[{"index":1,"side":0,"type":0},{"index":1,"side":1,"type":0}],"surface":0},"18:0":{"connections":[{"index":0,"side":2,"type":0},{"index":0,"side":3,"type":0}],"surface":0},"18:1":{"connections":[{"index":2,"side":2,"type":0},{"index":2,"side":3,"type":0}],"surface":0},"18:2":{"connections":[{"index":0,"side":0,"type":0},{"index":0,"side":1,"type":0}],"surface":0},"18:3":{"connections":[{"index":2,"side":0,"type":0},{"index":2,"side":1,"type":0}],"surface":0},"19:0":{"connections":[{"index":0,"side":2,"type":0},{"index":0,"side":3,"type":0}],"surface":0},"19:1":{"connections":[{"index":2,"side":2,"type":0},{"index":2,"side":3,"type":0}],"surface":0},"19:2":{"connections":[{"index":0,"side":0,"type":0},{"index":0,"side":1,"type":0}],"surface":0},"19:3":{"connections":[{"index":2,"side":0,"type":0},{"index":2,"side":1,"type":0}],"surface":0},"1:0":{"connections":[{"index":1,"side":2,"type":0},{"index":0,"side":0,"type":0}],"surface":0},"1:1":{"connections":[{"index":2,"side":0,"type":0},{"index":1,"side":3,"type":0}],"surface":0},"1:2":{"connections":[{"index":1,"side":2,"type":0},{"index":0,"side":1,"type":0}],"surface":0},"1:3":{"connections":[{"index":0,"side":2,"type":0},{"index":1,"side":0,"type":0}],"surface":0},"1:4":{"connections":[{"index":1,"side":3,"type":0},{"index":2,"side":1,"type":0}],"surface":0},"1:5":{"connections":[{"index":2,"side":2,"type":0},{"index":1,"side":1,"type":0}],"surface":0},"1:6":{"connections":[{"index":1,"side":0,"type":0},{"index":0,"side":3,"type":0}],"surface":0},"1:7":{"connections":[{"index":1,"side":1,"type":0},{"index":2,"side":3,"type":0}],"surface":0},"201:0":{"connections":[{"index":1,"side":2,"type":0},{"index":0,"side":0,"type":0}],"surface":2},"201:1":{"connections":[{"index":2,"side":0,"type":0},{"index":1,"side":3,"type":0}],"surface":2},"201:2":{"connections":[{"index":1,"side":2,"type":0},{"index":0,"side":1,"type":0}],"surface":2},"201:3":{"connections":[{"index":0,"side":2,"type":0},{"index":1,"side":0,"type":0}],"surface":2},"201:4":{"connections":[{"index":1,"side":3,"type":0},{"index":2,"side":1,"type":0}],"surface":2},"201:5":{"connections":[{"index":2,"side":2,"type":0},{"index":1,"side":1,"type":0}],"surface":2},"201:6":{"connections":[{"index":1,"side":0,"type":0},{"index":0,"side":3,"type":0}],"surface":2},"201:7":{"connections":[{"index":1,"side":1,"type":0},{"index":2,"side":3,"type":0}],"surface":2},"202:0":{"connections":[{"index":1,"side":2,"type":0},{"index":1,"side":0,"type":0}],"surface":2},"202:1":{"connections":[{"index":1,"side":0,"type":0},{"index":1,"side":3,"type":0}],"surface":2},"202:2":{"connections":[{"index":1,"side":2,"type":0},{"index":1,"side":1,"type":0}],"surface":2},"202:3":{"connections":[{"index":1,"side":1,"type":0},{"index":1,"side":3,"type":0}],"surface":2},"203:0":{"connections":[{"index":0,"side":2,"type":0},{"index":0,"side":0,"type":0}],"surface":2},"203:1":{"connections":[{"index":2,"side":0,"type":0},{"index":0,"side":3,"type":0}],"surface":2},"203:2":{"connections":[{"index":2,"side":1,"type":0},{"index":2,"side":3,"type":0}],"surface":2},"203:3":{"connections":[{"index":2,"side":2,"type":0},{"index":0,"side":1,"type":0}],"surface":2},"204:0":{"connections":[{"index":1,"side":2,"type":0},{"index":2,"side":0,"type":0}],"surface":2},"204:1":{"connections":[{"index":0,"side":0,"type":0},{"index":1,"side":3,"type":0}],"surface":2},"204:2":{"connections":[{"index":1,"side":2,"type":0},{"index":2,"side":1,"type":0}],"surface":2},"204:3":{"connections":[{"index":1,"side":0,"type":0},{"index":2,"side":2,"type":0}],"surface":2},"204:4":{"connections":[{"index":0,"side":1,"type":0},{"index":1,"side":3,"type":0}],"surface":2},"204:5":{"connections":[{"index":0,"side":2,"type":0},{"index":1,"side":1,"type":0}],"surface":2},"204:6":{"connections":[{"index":1,"side":0,"type":0},{"index":2,"side":3,"type":0}],"surface":2},"204:7":{"connections":[{"index":1,"side":1,"type":0},{"index":0,"side":3,"type":0}],"surface":2},"205:0":{"connections":[{"index":1,"side":2,"type":0},{"index":1,"side":3,"type":0}],"surface":2},"205:1":{"connections":[{"index":1,"side":0,"type":0},{"index":1,"side":1,"type":0}],"surface":2},"206:0":{"connections":[{"index":1,"side":2,"type":0},{"index":0,"side":3,"type":0}],"surface":2},"206:1":{"connections":[{"index":0,"side":2,"type":0},{"index":1,"side":3,"type":0}],"surface":2},"206:2":{"connections":[{"index":1,"side":2,"type":0},{"index":2,"side":3,"type":0}],"surface":2},"206:3":{"connections":[{"index":1,"side":0,"type":0},{"index":0,"side":1,"type":0}],"surface":2},"206:4":{"connections":[{"index":2,"side":2,"type":0},{"index":1,"side":3,"type":0}],"surface":2},"206:5":{"connections":[{"index":0,"side":0,"type":0},{"index":1,"side":1,"type":0}],"surface":2},"206:6":{"connections":[{"index":1,"side":0,"type":0},{"index":2,"side":1,"type":0}],"surface":2},"206:7":{"connections":[{"index":1,"side":1,"type":0},{"index":2,"side":0,"type":0}],"surface":2},"207:0":{"connections":[{"index":0,"side":2,"type":0},{"index":0,"side":1,"type":0}],"surface":2},"207:1":{"connections":[{"index":0,"side":3,"type":0},{"index":2,"side":1,"type":0}],"surface":2},"207:2":{"connections":[{"index":0,"side":0,"type":0},{"index":2,"side":2,"type":0}],"surface":2},"207:3":{"connections":[{"index":0,"side":0,"type":0},{"index":0,"side":3,"type":0}],"surface":2},"207:4":{"connections":[{"index":2,"side":0,"type":0},{"index":2,"side":3,"type":0}],"surface":2},"207:5":{"connections":[{"index":0,"side":1,"type":0},{"index":2,"side":3,"type":0}],"surface":2},"207:6":{"connections":[{"index":0,"side":2,"type":0},{"index":2,"side":0,"type":0}],"surface":2},"207:7":{"connections":[{"index":2,"side":2,"type":0},{"index":2,"side":1,"type":0}],"surface":2},"208:0":{"connections":[{"index":0,"side":2,"type":0},{"index":2,"side":1,"type":0}],"surface":2},"208:1":{"connections":[{"index":2,"side":2,"type":0},{"index":2,"side":0,"type":0}],"surface":2},"208:2":{"connections":[{"index":0,"side":0,"type":0},{"index":2,"side":3,"type":0}],"surface":2},"208:3":{"connections":[{"index":0,"side":1,"type":0},{"index":0,"side":3,"type":0}],"surface":2},"209:0":{"connections":[{"index":0,"side":2,"type":0},{"index":2,"side":3,"type":0}],"surface":2},"209:1":{"connections":[{"index":2,"side":2,"type":0},{"index":0,"side":3,"type":0}],"surface":2},"209:2":{"connections":[{"index":0,"side":1,"type":0},{"index":2,"side":0,"type":0}],"surface":2},"209:3":{"connections":[{"index":0,"side":0,"type":0},{"index":2,"side":1,"type":0}],"surface":2},"20:0":{"connections":[{"index":0,"side":2,"type":0},{"index":0,"side":3,"type":0}],"surface":0},"20:1":{"connections":[{"index":2,"side":2,"type":0},{"index":2,"side":3,"type":0}],"surface":0},"20:2":{"connections":[{"index":0,"side":0,"type":0},{"index":0,"side":1,"type":0}],"surface":0},"20:3":{"connections":[{"index":2,"side":0,"type":0},{"index":2,"side":1,"type":0}],"surface":0},"210:0":{"connections":[{"index":0,"side":2,"type":0},{"index":0,"side":3,"type":0}],"surface":2},"210:1":{"connections":[{"index":2,"side":2,"type":0},{"index":2,"side":3,"type":0}],"surface":2},"210:2":{"connections":[{"index":0,"side":0,"type":0},{"index":0,"side":1,"type":0}],"surface":2},"210:3":{"connections":[{"index":2,"side":0,"type":0},{"index":2,"side":1,"type":0}],"surface":2},"211:0":{"connections":[{"index":1,"side":2,"type":0},{"index":1,"side":3,"type":0}],"surface":2},"211:1":{"connections":[{"index":1,"side":0,"type":0},{"index":1,"side":1,"type":0}],"surface":2},"212:0":{"connections":[{"index":1,"side":2,"type":2},{"index":1,"side":3,"type":2}],"surface":2},"212:1":{"connections":[{"index":1,"side":0,"type":2},{"index":1,"side":1,"type":2}],"surface":2},"213:0":{"connections":[{"index":1,"side":2,"type":0},{"index":1,"side":3,"type":2}],"surface":2},"213:1":{"connections":[{"index":1,"side":0,"type":0},{"index":1,"side":1,"type":2}],"surface":2},"213:2":{"connections":[{"index":1,"side":2,"type":2},{"index":1,"side":3,"type":0}],"surface":2},"213:3":{"connections":[{"index":1,"side":0,"type":2},{"index":1,"side":1,"type":0}],"surface":2},"214:0":{"connections":[{"index":1,"side":2,"type":0},{"index":1,"side":3,"type":0}],"surface":2},"214:1":{"connections":[{"index":1,"side":0,"type":0},{"index":1,"side":1,"type":0}],"surface":2},"215:0":{"connections":[{"index":1,"side":2,"type":0},{"index":1,"side":3,"type":0}],"surface":2},"215:1":{"connections":[{"index":1,"side":0,"type":0},{"index":1,"side":1,"type":0}],"surface":2},"216:0":{"connections":[{"index":1,"side":2,"type":0},{"index":1,"side":3,"type":0}],"surface":2},"216:1":{"connections":[{"index":1,"side":0,"type":0},{"index":1,"side":1,"type":0}],"surface":2},"217:0":{"connections":[{"index":1,"side":2,"type":0},{"index":1,"side":3,"type":0}],"surface":2},"217:1":{"connections":[{"index":1,"side":0,"type":0},{"index":1,"side":1,"type":0}],"surface":2},"218:0":{"connections":[{"index":0,"side":2,"type":0},{"index":0,"side":3,"type":0}],"surface":2},"218:1":{"connections":[{"index":2,"side":2,"type":0},{"index":2,"side":3,"type":0}],"surface":2},"218:2":{"connections":[{"index":0,"side":0,"type":0},{"index":0,"side":1,"type":0}],"surface":2},"218:3":{"connections":[{"index":2,"side":0,"type":0},{"index":2,"side":1,"type":0}],"surface":2},"219:0":{"connections":[{"index":0,"side":2,"type":0},{"index":0,"side":3,"type":0}],"surface":2},"219:1":{"connections":[{"index":2,"side":2,"type":0},{"index":2,"side":3,"type":0}],"surface":2},"219:2":{"connections":[{"index":0,"side":0,"type":0},{"index":0,"side":1,"type":0}],"surface":2},"219:3":{"connections":[{"index":2,"side":0,"type":0},{"index":2,"side":1,"type":0}],"surface":2},"21:0":{"connections":[{"index":1,"side":1,"type":1},{"index":1,"side":3,"type":0}],"surface":0},"21:1":{"connections":[{"index":1,"side":2,"type":1},{"index":1,"side":1,"type":0}],"surface":0},"21:2":{"connections":[{"index":1,"side":0,"type":1},{"index":1,"side":2,"type":0}],"surface":0},"21:3":{"connections":[{"index":1,"side":3,"type":1},{"index":1,"side":0,"type":0}],"surface":0},"21:4":{"connections":[{"index":1,"side":0,"type":1},{"index":1,"side":3,"type":0}],"surface":0},"21:5":{"connections":[{"index":1,"side":2,"type":1},{"index":1,"side":0,"type":0}],"surface":0},"21:6":{"connections":[{"index":1,"side":1,"type":1},{"index":1,"side":2,"type":0}],"surface":0},"21:7":{"connections":[{"index":1,"side":3,"type":1},{"index":1,"side":1,"type":0}],"surface":0},"220:0":{"connections":[{"index":0,"side":2,"type":0},{"index":0,"side":3,"type":0}],"surface":2},"220:1":{"connections":[{"index":2,"side":2,"type":0},{"index":2,"side":3,"type":0}],"surface":2},"220:2":{"connections":[{"index":0,"side":0,"type":0},{"index":0,"side":1,"type":0}],"surface":2},"220:3":{"connections":[{"index":2,"side":0,"type":0},{"index":2,"side":1,"type":0}],"surface":2},"221:0":{"connections":[{"index":1,"side":1,"type":1},{"index":1,"side":3,"type":0}],"surface":2},"221:1":{"connections":[{"index":1,"side":2,"type":1},{"index":1,"side":1,"type":0}],"surface":2},"221:2":{"connections":[{"index":1,"side":0,"type":1},{"index":1,"side":2,"type":0}],"surface":2},"221:3":{"connections":[{"index":1,"side":3,"type":1},{"index":1,"side":0,"type":0}],"surface":2},"221:4":{"connections":[{"index":1,"side":0,"type":1},{"index":1,"side":3,"type":0}],"surface":2},"221:5":{"connections":[{"index":1,"side":2,"type":1},{"index":1,"side":0,"type":0}],"surface":2},"221:6":{"connections":[{"index":1,"side":1,"type":1},{"index":1,"side":2,"type":0}],"surface":2},"221:7":{"connections":[{"index":1,"side":3,"type":1},{"index":1,"side":1,"type":0}],"surface":2},"222:0":{"connections":[{"index":1,"side":2,"type":1},{"index":1,"side":0,"type":1}],"surface":2},"222:1":{"connections":[{"index":1,"side":0,"type":1},{"index":1,"side":3,"type":1}],"surface":2},"222:2":{"connections":[{"index":1,"side":1,"type":1},{"index":1,"side":2,"type":1}],"surface":2},"222:3":{"connections":[{"index":1,"side":3,"type":1},{"index":1,"side":1,"type":1}],"surface":2},"223:0":{"connections":[{"index":0,"side":2,"type":0},{"index":0,"side":3,"type":0}],"surface":2},"223:1":{"connections":[{"index":2,"side":2,"type":0},{"index":2,"side":3,"type":0}],"surface":2},"223:2":{"connections":[{"index":0,"side":0,"type":0},{"index":0,"side":1,"type":0}],"surface":2},"223:3":{"connections":[{"index":2,"side":0,"type":0},{"index":2,"side":1,"type":0}],"surface":2},"224:0":{"connections":[{"index":1,"side":2,"type":4},{"index":0,"side":0,"type":3}],"surface":2},"224:1":{"connections":[{"index":2,"side":0,"type":3},{"index":1,"side":3,"type":4}],"surface":2},"224:2":{"connections":[{"index":1,"side":2,"type":4},{"index":0,"side":1,"type":3}],"surface":2},"224:3":{"connections":[{"index":0,"side":2,"type":3},{"index":1,"side":0,"type":4}],"surface":2},"224:4":{"connections":[{"index":1,"side":3,"type":4},{"index":2,"side":1,"type":3}],"surface":2},"224:5":{"connections":[{"index":2,"side":2,"type":3},{"index":1,"side":1,"type":4}],"surface":2},"224:6":{"connections":[{"index":1,"side":0,"type":4},{"index":0,"side":3,"type":3}],"surface":2},"224:7":{"connections":[{"index":1,"side":1,"type":4},{"index":2,"side":3,"type":3}],"surface":2},"225:0":{"connections":[{"index":1,"side":2,"type":4},{"index":0,"side":0,"type":0}],"surface":2},"225:1":{"connections":[{"index":2,"side":0,"type":0},{"index":1,"side":3,"type":4}],"surface":2},"225:2":{"connections":[{"index":1,"side":2,"type":4},{"index":0,"side":1,"type":0}],"surface":2},"225:3":{"connections":[{"index":0,"side":2,"type":0},{"index":1,"side":0,"type":4}],"surface":2},"225:4":{"connections":[{"index":1,"side":3,"type":4},{"index":2,"side":1,"type":0}],"surface":2},"225:5":{"connections":[{"index":2,"side":2,"type":0},{"index":1,"side":1,"type":4}],"surface":2},"225:6":{"connections":[{"index":1,"side":0,"type":4},{"index":0,"side":3,"type":0}],"surface":2},"225:7":{"connections":[{"index":1,"side":1,"type":4},{"index":2,"side":3,"type":0}],"surface":2},"226:0":{"connections":[{"index":1,"side":2,"type":3},{"index":0,"side":3,"type":3}],"surface":2},"226:1":{"connections":[{"index":0,"side":2,"type":3},{"index":1,"side":3,"type":3}],"surface":2},"226:2":{"connections":[{"index":1,"side":2,"type":3},{"index":2,"side":3,"type":3}],"surface":2},"226:3":{"connections":[{"index":1,"side":0,"type":3},{"index":0,"side":1,"type":3}],"surface":2},"226:4":{"connections":[{"index":2,"side":2,"type":3},{"index":1,"side":3,"type":3}],"surface":2},"226:5":{"connections":[{"index":0,"side":0,"type":3},{"index":1,"side":1,"type":3}],"surface":2},"226:6":{"connections":[{"index":1,"side":0,"type":3},{"index":2,"side":1,"type":3}],"surface":2},"226:7":{"connections":[{"index":1,"side":1,"type":3},{"index":2,"side":0,"type":3}],"surface":2},"227:0":{"connections":[{"index":1,"side":2,"type":0},{"index":0,"side":3,"type":3}],"surface":2},"227:1":{"connections":[{"index":0,"side":2,"type":3},{"index":1,"side":3,"type":0}],"surface":2},"227:2":{"connections":[{"index":1,"side":2,"type":0},{"index":2,"side":3,"type":3}],"surface":2},"227:3":{"connections":[{"index":1,"side":0,"type":0},{"index":0,"side":1,"type":3}],"surface":2},"227:4":{"connections":[{"index":2,"side":2,"type":3},{"index":1,"side":3,"type":0}],"surface":2},"227:5":{"connections":[{"index":0,"side":0,"type":3},{"index":1,"side":1,"type":0}],"surface":2},"227:6":{"connections":[{"index":1,"side":0,"type":0},{"index":2,"side":1,"type":3}],"surface":2},"227:7":{"connections":[{"index":1,"side":1,"type":0},{"index":2,"side":0,"type":3}],"surface":2},"228:0":{"connections":[{"index":1,"side":2,"type":3},{"index":0,"side":3,"type":0}],"surface":2},"228:1":{"connections":[{"index":0,"side":2,"type":0},{"index":1,"side":3,"type":3}],"surface":2},"228:2":{"connections":[{"index":1,"side":2,"type":3},{"index":2,"side":3,"type":0}],"surface":2},"228:3":{"connections":[{"index":1,"side":0,"type":3},{"index":0,"side":1,"type":0}],"surface":2},"228:4":{"connections":[{"index":2,"side":2,"type":0},{"index":1,"side":3,"type":3}],"surface":2},"228:5":{"connections":[{"index":0,"side":0,"type":0},{"index":1,"side":1,"type":3}],"surface":2},"228:6":{"connections":[{"index":1,"side":0,"type":3},{"index":2,"side":1,"type":0}],"surface":2},"228:7":{"connections":[{"index":1,"side":1,"type":3},{"index":2,"side":0,"type":0}],"surface":2},"22:0":{"connections":[{"index":1,"side":2,"type":1},{"index":1,"side":0,"type":1}],"surface":0},"22:1":{"connections":[{"index":1,"side":0,"type":1},{"index":1,"side":3,"type":1}],"surface":0},"22:2":{"connections":[{"index":1,"side":1,"type":1},{"index":1,"side":2,"type":1}],"surface":0},"22:3":{"connections":[{"index":1,"side":3,"type":1},{"index":1,"side":1,"type":1}],"surface":0},"23:0":{"connections":[{"index":0,"side":2,"type":0},{"index":0,"side":3,"type":0}],"surface":0},"23:1":{"connections":[{"index":2,"side":2,"type":0},{"index":2,"side":3,"type":0}],"surface":0},"23:2":{"connections":[{"index":0,"side":0,"type":0},{"index":0,"side":1,"type":0}],"surface":0},"23:3":{"connections":[{"index":2,"side":0,"type":0},{"index":2,"side":1,"type":0}],"surface":0},"24:0":{"connections":[{"index":1,"side":2,"type":4},{"index":0,"side":0,"type":3}],"surface":0},"24:1":{"connections":[{"index":2,"side":0,"type":3},{"index":1,"side":3,"type":4}],"surface":0},"24:2":{"connections":[{"index":1,"side":2,"type":4},{"index":0,"side":1,"type":3}],"surface":0},"24:3":{"connections":[{"index":0,"side":2,"type":3},{"index":1,"side":0,"type":4}],"surface":0},"24:4":{"connections":[{"index":1,"side":3,"type":4},{"index":2,"side":1,"type":3}],"surface":0},"24:5":{"connections":[{"index":2,"side":2,"type":3},{"index":1,"side":1,"type":4}],"surface":0},"24:6":{"connections":[{"index":1,"side":0,"type":4},{"index":0,"side":3,"type":3}],"surface":0},"24:7":{"connections":[{"index":1,"side":1,"type":4},{"index":2,"side":3,"type":3}],"surface":0},"25:0":{"connections":[{"index":1,"side":2,"type":4},{"index":0,"side":0,"type":0}],"surface":0},"25:1":{"connections":[{"index":2,"side":0,"type":0},{"index":1,"side":3,"type":4}],"surface":0},"25:2":{"connections":[{"index":1,"side":2,"type":4},{"index":0,"side":1,"type":0}],"surface":0},"25:3":{"connections":[{"index":0,"side":2,"type":0},{"index":1,"side":0,"type":4}],"surface":0},"25:4":{"connections":[{"index":1,"side":3,"type":4},{"index":2,"side":1,"type":0}],"surface":0},"25:5":{"connections":[{"index":2,"side":2,"type":0},{"index":1,"side":1,"type":4}],"surface":0},"25:6":{"connections":[{"index":1,"side":0,"type":4},{"index":0,"side":3,"type":0}],"surface":0},"25:7":{"connections":[{"index":1,"side":1,"type":4},{"index":2,"side":3,"type":0}],"surface":0},"26:0":{"connections":[{"index":1,"side":2,"type":3},{"index":0,"side":3,"type":3}],"surface":0},"26:1":{"connections":[{"index":0,"side":2,"type":3},{"index":1,"side":3,"type":3}],"surface":0},"26:2":{"connections":[{"index":1,"side":2,"type":3},{"index":2,"side":3,"type":3}],"surface":0},"26:3":{"connections":[{"index":1,"side":0,"type":3},{"index":0,"side":1,"type":3}],"surface":0},"26:4":{"connections":[{"index":2,"side":2,"type":3},{"index":1,"side":3,"type":3}],"surface":0},"26:5":{"connections":[{"index":0,"side":0,"type":3},{"index":1,"side":1,"type":3}],"surface":0},"26:6":{"connections":[{"index":1,"side":0,"type":3},{"index":2,"side":1,"type":3}],"surface":0},"26:7":{"connections":[{"index":1,"side":1,"type":3},{"index":2,"side":0,"type":3}],"surface":0},"27:0":{"connections":[{"index":1,"side":2,"type":0},{"index":0,"side":3,"type":3}],"surface":0},"27:1":{"connections":[{"index":0,"side":2,"type":3},{"index":1,"side":3,"type":0}],"surface":0},"27:2":{"connections":[{"index":1,"side":2,"type":0},{"index":2,"side":3,"type":3}],"surface":0},"27:3":{"connections":[{"index":1,"side":0,"type":0},{"index":0,"side":1,"type":3}],"surface":0},"27:4":{"connections":[{"index":2,"side":2,"type":3},{"index":1,"side":3,"type":0}],"surface":0},"27:5":{"connections":[{"index":0,"side":0,"type":3},{"index":1,"side":1,"type":0}],"surface":0},"27:6":{"connections":[{"index":1,"side":0,"type":0},{"index":2,"side":1,"type":3}],"surface":0},"27:7":{"connections":[{"index":1,"side":1,"type":0},{"index":2,"side":0,"type":3}],"surface":0},"28:0":{"connections":[{"index":1,"side":2,"type":3},{"index":0,"side":3,"type":0}],"surface":0},"28:1":{"connections":[{"index":0,"side":2,"type":0},{"index":1,"side":3,"type":3}],"surface":0},"28:2":{"connections":[{"index":1,"side":2,"type":3},{"index":2,"side":3,"type":0}],"surface":0},"28:3":{"connections":[{"index":1,"side":0,"type":3},{"index":0,"side":1,"type":0}],"surface":0},"28:4":{"connections":[{"index":2,"side":2,"type":0},{"index":1,"side":3,"type":3}],"surface":0},"28:5":{"connections":[{"index":0,"side":0,"type":0},{"index":1,"side":1,"type":3}],"surface":0},"28:6":{"connections":[{"index":1,"side":0,"type":3},{"index":2,"side":1,"type":0}],"surface":0},"28:7":{"connections":[{"index":1,"side":1,"type":3},{"index":2,"side":0,"type":0}],"surface":0},"2:0":{"connections":[{"index":1,"side":2,"type":0},{"index":1,"side":0,"type":0}],"surface":0},"2:1":{"connections":[{"index":1,"side":0,"type":0},{"index":1,"side":3,"type":0}],"surface":0},"2:2":{"connections":[{"index":1,"side":2,"type":0},{"index":1,"side":1,"type":0}],"surface":0},"2:3":{"connections":[{"index":1,"side":1,"type":0},{"index":1,"side":3,"type":0}],"surface":0},"3:0":{"connections":[{"index":0,"side":2,"type":0},{"index":0,"side":0,"type":0}],"surface":0},"3:1":{"connections":[{"index":2,"side":0,"type":0},{"index":0,"side":3,"type":0}],"surface":0},"3:2":{"connections":[{"index":2,"side":1,"type":0},{"index":2,"side":3,"type":0}],"surface":0},"3:3":{"connections":[{"index":2,"side":2,"type":0},{"index":0,"side":1,"type":0}],"surface":0},"4:0":{"connections":[{"index":1,"side":2,"type":0},{"index":2,"side":0,"type":0}],"surface":0},"4:1":{"connections":[{"index":0,"side":0,"type":0},{"index":1,"side":3,"type":0}],"surface":0},"4:2":{"connections":[{"index":1,"side":2,"type":0},{"index":2,"side":1,"type":0}],"surface":0},"4:3":{"connections":[{"index":1,"side":0,"type":0},{"index":2,"side":2,"type":0}],"surface":0},"4:4":{"connections":[{"index":0,"side":1,"type":0},{"index":1,"side":3,"type":0}],"surface":0},"4:5":{"connections":[{"index":0,"side":2,"type":0},{"index":1,"side":1,"type":0}],"surface":0},"4:6":{"connections":[{"index":1,"side":0,"type":0},{"index":2,"side":3,"type":0}],"surface":0},"4:7":{"connections":[{"index":1,"side":1,"type":0},{"index":0,"side":3,"type":0}],"surface":0},"5:0":{"connections":[{"index":1,"side":2,"type":0},{"index":1,"side":3,"type":0}],"surface":0},"5:1":{"connections":[{"index":1,"side":0,"type":0},{"index":1,"side":1,"type":0}],"surface":0},"6:0":{"connections":[{"index":1,"side":2,"type":0},{"index":0,"side":3,"type":0}],"surface":0},"6:1":{"connections":[{"index":0,"side":2,"type":0},{"index":1,"side":3,"type":0}],"surface":0},"6:2":{"connections":[{"index":1,"side":2,"type":0},{"index":2,"side":3,"type":0}],"surface":0},"6:3":{"connections":[{"index":1,"side":0,"type":0},{"index":0,"side":1,"type":0}],"surface":0},"6:4":{"connections":[{"index":2,"side":2,"type":0},{"index":1,"side":3,"type":0}],"surface":0},"6:5":{"connections":[{"index":0,"side":0,"type":0},{"index":1,"side":1,"type":0}],"surface":0},"6:6":{"connections":[{"index":1,"side":0,"type":0},{"index":2,"side":1,"type":0}],"surface":0},"6:7":{"connections":[{"index":1,"side":1,"type":0},{"index":2,"side":0,"type":0}],"surface":0},"7:0":{"connections":[{"index":0,"side":2,"type":0},{"index":0,"side":1,"type":0}],"surface":0},"7:1":{"connections":[{"index":0,"side":3,"type":0},{"index":2,"side":1,"type":0}],"surface":0},"7:2":{"connections":[{"index":0,"side":0,"type":0},{"index":2,"side":2,"type":0}],"surface":0},"7:3":{"connections":[{"index":0,"side":0,"type":0},{"index":0,"side":3,"type":0}],"surface":0},"7:4":{"connections":[{"index":2,"side":0,"type":0},{"index":2,"side":3,"type":0}],"surface":0},"7:5":{"connections":[{"index":0,"side":1,"type":0},{"index":2,"side":3,"type":0}],"surface":0},"7:6":{"connections":[{"index":0,"side":2,"type":0},{"index":2,"side":0,"type":0}],"surface":0},"7:7":{"connections":[{"index":2,"side":2,"type":0},{"index":2,"side":1,"type":0}],"surface":0},"8:0":{"connections":[{"index":0,"side":2,"type":0},{"index":2,"side":1,"type":0}],"surface":0},"8:1":{"connections":[{"index":2,"side":2,"type":0},{"index":2,"side":0,"type":0}],"surface":0},"8:2":{"connections":[{"index":0,"side":0,"type":0},{"index":2,"side":3,"type":0}],"surface":0},"8:3":{"connections":[{"index":0,"side":1,"type":0},{"index":0,"side":3,"type":0}],"surface":0},"9:0":{"connections":[{"index":0,"side":2,"type":0},{"index":2,"side":3,"type":0}],"surface":0},"9:1":{"connections":[{"index":2,"side":2,"type":0},{"index":0,"side":3,"type":0}],"surface":0},"9:2":{"connections":[{"index":0,"side":1,"type":0},{"index":2,"side":0,"type":0}],"surface":0},"9:3":{"connections":[{"index":0,"side":0,"type":0},{"index":2,"side":1,"type":0}],"surface":0}},"schema":"ald-track-atlas-preview-v1","source":"Zorro909/driving_sim_rs src/data/track_catalog.json at d8ab74c25df70b6a86ed101080e33d5fb785ea6f"}
backend_policy.py DELETED
@@ -1,21 +0,0 @@
1
- """Deployment identity and fail-closed GPU selection, independent of UI labels."""
2
- import os
3
- import json
4
- import subprocess
5
-
6
- UPSTREAM = 'd8ab74c25df70b6a86ed101080e33d5fb785ea6f'
7
-
8
-
9
- def backend_args(config, binary, scratch):
10
- args = ['--math-profile', 'proton']
11
- if os.environ.get('ALD_REQUIRE_GPU') != '1':
12
- return args, []
13
- if not scratch:
14
- raise ValueError('GPU worker currently supports positive-mutation training only; replay stays on the CPU Space')
15
- check = subprocess.run([str(binary), 'gpu-info'], capture_output=True, text=True, timeout=30)
16
- if check.returncode:
17
- raise RuntimeError('GPU preflight failed; CPU fallback is disabled: ' + check.stderr[-1500:])
18
- info=json.loads(check.stdout)
19
- if not info.get('device') or info.get('kernels') != 'ok' or info.get('layout') != 'ok':
20
- raise RuntimeError('GPU device and kernel acceptance missing; CPU fallback is disabled')
21
- return args, ['--gpu']
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
batch_runner.py DELETED
@@ -1,42 +0,0 @@
1
- """Serial finite batches, frozen recipes, explicit parent lineage, no auto-resume."""
2
- import base64,copy,hashlib,json,threading,time,uuid
3
- from pathlib import Path
4
- class Batches:
5
- def __init__(self,root,store,parse,make_job,execute):
6
- self.root=Path(root);self.root.mkdir(exist_ok=True);self.store=store;self.parse=parse;self.make_job=make_job;self.execute=execute;self.items={};self.guard=threading.RLock()
7
- for p in sorted(self.root.glob('*/status.json')):
8
- b=json.loads(p.read_text());b['cancel']=threading.Event()
9
- if b['state'] in ('queued','running'):b['state']='interrupted';self.save(b)
10
- self.items[b['id']]=b
11
- def public(self,b):return {k:v for k,v in b.items() if k!='cancel'}
12
- def save(self,b):
13
- with self.guard:
14
- f=self.root/b['id']/'status.json';tmp=f.with_suffix('.tmp');tmp.write_text(json.dumps(self.public(b),indent=2));tmp.replace(f)
15
- def active(self):return any(b['state'] in ('queued','running') for b in self.items.values())
16
- def start(self,slot,data):
17
- template,_=self.parse(data);manifest=self.store.resolve(slot)
18
- id='batch-'+time.strftime('%Y%m%d-%H%M%S')+'-'+uuid.uuid4().hex[:6];d=self.root/id;d.mkdir();(d/'input.evolution').write_bytes(data)
19
- manifest['input_sha256']=hashlib.sha256(data).hexdigest();(d/'manifest.json').write_text(json.dumps(manifest,indent=2))
20
- b={'id':id,'name':manifest['name'],'slot':slot,'state':'queued','step':0,'total':len(manifest['steps']),'carry':manifest['carry'],'manifest':manifest,'jobs':[],'current_job':None,'cancel':threading.Event()};self.items[id]=b;self.save(b)
21
- threading.Thread(target=self.worker,args=(b,data),daemon=True).start();return self.public(b)
22
- def worker(self,b,original):
23
- current=original
24
- try:
25
- b['state']='running';self.save(b)
26
- for i,step in enumerate(b['manifest']['steps']):
27
- if b['cancel'].is_set():raise InterruptedError('Batch stopped')
28
- parent=current if b['carry'] else original
29
- job=self.make_job(copy.deepcopy(step['config']),parent,b['id']);b['current_job']=job['id'];b['step']=i+1;b['jobs'].append({'id':job['id'],'run_slot':step['run_slot'],'input_sha256':hashlib.sha256(parent).hexdigest()});self.save(b)
30
- if b['cancel'].is_set():job['cancel'].set()
31
- self.execute(job)
32
- if job['state']=='stopped' or b['cancel'].is_set():raise InterruptedError('Batch stopped')
33
- if job['state']!='complete':raise RuntimeError(f'Run {step["run_slot"]} failed: {job.get("error",job["state"])}')
34
- current=(Path(job['output_dir'])/'candidate.evolution').read_bytes();b['last_candidate']=str(Path(job['output_dir'])/'candidate.evolution');self.save(b)
35
- b['state']='complete'
36
- except InterruptedError:b['state']='stopped'
37
- except Exception as e:b['state']='failed';b['error']=str(e)
38
- finally:self.save(b)
39
- def stop(self,id,jobs):
40
- b=self.items[id];b['cancel'].set();j=jobs.get(b['current_job'])
41
- if j:j['cancel'].set()
42
- return self.public(b)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bin/altd-sim CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:2f2f2144ae14b0ef599ca8510f95712da00243c6875881491d384b394e7499f7
3
- size 13911800
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:0135ecc3d435a9d327be7a92e048cfb5c5291a02ef1e0dddd6ead1cc19b31166
3
+ size 15774792
bin/libaltd_gpu.so CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:279d6353b4c691686d6aeeae6abfd4a82b959e9b604f079a6c45f9823b48a87a
3
- size 3933424
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:0064e747543251bab90cb966f8df00b010716a92cc75910229d42c9b24c1dac9
3
+ size 12291032
client.js CHANGED
@@ -14,6 +14,7 @@ let batchReceipt = null;
14
  const hostedStandalone = location.hostname.endsWith('.hf.space') && window.self === window.top;
15
  const say = text => { $('status').textContent = text; };
16
  const trackLibrary=window.TrackLibrary?.mount({document,fetch,digest:sha});
 
17
  const trackSource=()=>trackLibrary?trackLibrary.file():Promise.resolve($('track').files[0]);
18
  function buttons() {
19
  trackLibrary?.setBusy(busy || !!job);
@@ -24,7 +25,7 @@ function buttons() {
24
  $('backend').disabled = busy || !!job || !capabilitiesReady;
25
  $('download').disabled = busy || !job;
26
  $('erase').disabled = busy || !job;
27
- $('automatic').disabled = busy || !!job;
28
  $('saveLocal').disabled = busy || !localResult;
29
  $('forgetLocal').disabled = busy || !localResult;
30
  $('track').disabled=busy || !!job;
@@ -122,7 +123,7 @@ $('run').onclick = async () => {
122
  busy=true; buttons(); say(window.getTrainingSettings?'Processing the training run…':'Processing the bounded test…');
123
  try {
124
  const trackInfo=trackLibrary?.info();
125
- const body={track:await encoded(await trackSource()),network:await encoded(networkSource()),automatic:$('automatic').checked,backend:$('backend').value};
126
  if(window.getTrainingSettings)body.settings=window.getTrainingSettings();
127
  job=await submit(body);localResult=null;
128
  clearInterval(progress);
@@ -153,7 +154,7 @@ $('run').onclick = async () => {
153
  $('runSummary').textContent='Elapsed: '+((performance.now()-started)/1000).toFixed(1)+' s\nNo downloadable result was received. A connection error does not prove the server stopped.';
154
  say(error.message);
155
  }
156
- finally {clearInterval(progress);busy=false; buttons();}
157
  };
158
  $('download').onclick = async () => {
159
  busy=true; buttons();
@@ -163,7 +164,7 @@ $('download').onclick = async () => {
163
  localResult=new Blob([bytes]); saveLocal();
164
  const acknowledgment=await acknowledge(job,receipt);
165
  if (acknowledgment.deleted) { $('runState').textContent='COMPLETE — result received; server copy deleted'; job=null; say('Result received by browser. Server result deleted. Save your local download; server retrieval is no longer available.'); }
166
- else say('Result received by browser. Verify your saved file, then select Delete now; repeat downloads remain available until expiry.');
167
  } catch (error) { say(error.message+' If receipt acknowledgment failed, use Delete now; automatic expiry still applies.'); }
168
  finally {busy=false; buttons();}
169
  };
@@ -251,7 +252,9 @@ async function connect(){
251
  if(capabilities.cpu!==true)throw new Error('CPU unavailable');
252
  gpuTransport=capabilities.gpu_transport??null;
253
  $('gpuOption').disabled=!capabilities.gpu;
254
- $('backendNote').textContent=capabilities.gpu?(hostedStandalone?'CPU uses no GPU allowance. Optional HF sign-in identifies account GPU requests; without sign-in, direct requests may use the limited anonymous allowance. No automatic switching.':'CPU uses no GPU allowance. GPU is subject to HF quota through the official client; optional HF sign-in explicitly identifies the caller. No automatic switching.'):'CPU available. GPU is not connected on this deployment; no GPU allowance is needed for CPU.';
 
 
255
  capabilitiesReady=true; buttons();
256
  say('Connected. Choose your track and network, then run the test.');
257
  } catch(error) {
 
14
  const hostedStandalone = location.hostname.endsWith('.hf.space') && window.self === window.top;
15
  const say = text => { $('status').textContent = text; };
16
  const trackLibrary=window.TrackLibrary?.mount({document,fetch,digest:sha});
17
+ window.TrackMap?.mount({document,fetch,picker:trackLibrary});
18
  const trackSource=()=>trackLibrary?trackLibrary.file():Promise.resolve($('track').files[0]);
19
  function buttons() {
20
  trackLibrary?.setBusy(busy || !!job);
 
25
  $('backend').disabled = busy || !!job || !capabilitiesReady;
26
  $('download').disabled = busy || !job;
27
  $('erase').disabled = busy || !job;
28
+ $('keepServer').disabled = busy || !!job;
29
  $('saveLocal').disabled = busy || !localResult;
30
  $('forgetLocal').disabled = busy || !localResult;
31
  $('track').disabled=busy || !!job;
 
123
  busy=true; buttons(); say(window.getTrainingSettings?'Processing the training run…':'Processing the bounded test…');
124
  try {
125
  const trackInfo=trackLibrary?.info();
126
+ const body={track:await encoded(await trackSource()),network:await encoded(networkSource()),automatic:!$('keepServer').checked,backend:$('backend').value};
127
  if(window.getTrainingSettings)body.settings=window.getTrainingSettings();
128
  job=await submit(body);localResult=null;
129
  clearInterval(progress);
 
154
  $('runSummary').textContent='Elapsed: '+((performance.now()-started)/1000).toFixed(1)+' s\nNo downloadable result was received. A connection error does not prove the server stopped.';
155
  say(error.message);
156
  }
157
+ finally {clearInterval(progress);busy=false;$('keepServer').checked=false;buttons();}
158
  };
159
  $('download').onclick = async () => {
160
  busy=true; buttons();
 
164
  localResult=new Blob([bytes]); saveLocal();
165
  const acknowledgment=await acknowledge(job,receipt);
166
  if (acknowledgment.deleted) { $('runState').textContent='COMPLETE — result received; server copy deleted'; job=null; say('Result received by browser. Server result deleted. Save your local download; server retrieval is no longer available.'); }
167
+ else say('Result received by browser. The server copy is available for another download until its five-minute deadline; use Delete now to remove it sooner.');
168
  } catch (error) { say(error.message+' If receipt acknowledgment failed, use Delete now; automatic expiry still applies.'); }
169
  finally {busy=false; buttons();}
170
  };
 
252
  if(capabilities.cpu!==true)throw new Error('CPU unavailable');
253
  gpuTransport=capabilities.gpu_transport??null;
254
  $('gpuOption').disabled=!capabilities.gpu;
255
+ $('backendNote').textContent=capabilities.gpu?(hostedStandalone?'CPU is anonymous. GPU may use a limited anonymous allowance or your optional HF account allowance.':'CPU is anonymous. GPU requires an available HF allowance.'):'CPU training is ready; no sign-in or GPU allowance needed.';
256
+ $('gpuAccount').hidden=!capabilities.gpu;
257
+ $('computeBlock').hidden=!capabilities.gpu;
258
  capabilitiesReady=true; buttons();
259
  say('Connected. Choose your track and network, then run the test.');
260
  } catch(error) {
cloud-contract.json DELETED
@@ -1 +0,0 @@
1
- {"sensors": [{"$type": "raycast", "Length": 200.00003, "Degrees": -90}, {"$type": "raycast", "Length": 719.61523, "Degrees": -30}, {"$type": "raycast", "Length": 800, "Degrees": 0}, {"$type": "raycast", "Length": 719.61523, "Degrees": 30}, {"$type": "raycast", "Length": 200.00003, "Degrees": 90}, {"$type": "speed"}]}
 
 
cloud_core.py DELETED
@@ -1,5 +0,0 @@
1
- import json
2
- from pathlib import Path
3
- ENTRY=json.loads((Path(__file__).parent/'cloud-contract.json').read_text())
4
- def network(v):
5
- return {'weights':[[v[i*4:(i+1)*4] for i in range(6)],[v[28+i*2:28+(i+1)*2] for i in range(4)]],'biases':[v[24:28],v[36:38]]}
 
 
 
 
 
 
cloud_probe.py DELETED
@@ -1,63 +0,0 @@
1
- """Fixed synthetic CPU/CUDA smoke test; no uploads or retained model artifacts."""
2
- import gzip
3
- import hashlib
4
- import json
5
- import os
6
- from pathlib import Path
7
- import subprocess
8
- import tempfile
9
- import time
10
-
11
- ROOT = Path(__file__).resolve().parent
12
-
13
- def run_probe(gpu=False):
14
- from probe_core import verify_artifacts, qualify
15
- verify_artifacts()
16
- qualification = qualify() if gpu else None
17
- if gpu and not qualification['qualified_for_next_test']:
18
- return {'status':'qualification_failed','qualification':qualification}
19
- binary=ROOT/'bin/altd-sim'
20
- binary.chmod(0o755)
21
- network={'shape':[1,2],'weights':[[[0.0,0.0]]],'biases':[[0.0,1.0]],
22
- 'inputs':['speed'],'outputs':['Steering','Acceleration']}
23
- model={'sensor_layout':{'names':['speed'],'sensors':[{'$type':'speed'}]}}
24
- settings={'population':4,'selection_algorithm':'best','selection_size':1,
25
- 'crossover':'none','mutation_rate':0.01,'adaptive_mutation':False,'weight_decay':0,
26
- 'preserve_parents':'on_custom','preserve_parents_size':1,
27
- 'rewards':[{'metric':'total_score','type':'default','weight':1}]}
28
- report={'backend_requested':'cuda' if gpu else 'cpu','population':4,'generations':1,
29
- 'ticks':60,'seed':42,'qualification':qualification,'speedup_verified':False}
30
- with tempfile.TemporaryDirectory(prefix='tiga-probe-') as directory:
31
- work=Path(directory)
32
- for name,value in [('network',network),('model',model),('settings',settings)]:
33
- (work/(name+'.json')).write_text(json.dumps(value))
34
- command=[str(binary),'--math-profile','proton','--threads','1','train-scratch']
35
- if gpu: command+=['--gpu']
36
- command+=['--scene',str(ROOT/'tracks/A01 Beginner.scene.json'),
37
- '--spawn-trace',str(ROOT/'tracks/A01 Beginner.spawn.json'),
38
- '--network',str(work/'network.json'),'--init-network',str(work/'network.json'),
39
- '--model',str(work/'model.json'),'--settings',str(work/'settings.json'),
40
- '--shape','1,2','--population','4','--generations','1','--ticks','60',
41
- '--seed','42','--batch-count','2','--out-dir',str(work/'out'),
42
- '--mutation-start','.01','--mutation-end','.01','--schedule','linear','--save-final-candidate']
43
- # Preserve only native-loader/device plumbing, never provider credentials.
44
- keys=('PATH','LD_LIBRARY_PATH','LD_PRELOAD','CUDA_VISIBLE_DEVICES','NVIDIA_VISIBLE_DEVICES')
45
- env={k:os.environ[k] for k in keys if k in os.environ}
46
- env.update(HOME=directory,TMPDIR=directory,ALTD_GPU_LIB=str(ROOT/'bin/libaltd_gpu.so'))
47
- started=time.perf_counter()
48
- try:
49
- result=subprocess.run(command,cwd=work,env=env,capture_output=True,text=True,timeout=30)
50
- report.update(returncode=result.returncode,wall_seconds=time.perf_counter()-started,
51
- stderr=result.stderr[-4000:],stdout=result.stdout[-4000:])
52
- candidate=work/'out/candidate.json'
53
- report['status']='failed'
54
- if result.returncode==0 and candidate.is_file():
55
- value=json.loads(candidate.read_text())
56
- report.update(status='candidate_created',shape=value['shape'],
57
- candidate_sha256=hashlib.sha256(candidate.read_bytes()).hexdigest(),
58
- history=[json.loads(line) for line in (work/'out/log.jsonl').read_text().splitlines()])
59
- except subprocess.TimeoutExpired:
60
- report.update(status='timeout',wall_seconds=time.perf_counter()-started)
61
- report['temporary_directory_removed']=not work.exists()
62
- report['candidate_retained']=False
63
- return report
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
delivery.py CHANGED
@@ -50,9 +50,9 @@ class ResultStore:
50
  if len(self.jobs)>=16 or self.retained_bytes+len(data)>self.max_bytes:
51
  raise CapacityExceeded()
52
  ident, key = secrets.token_urlsafe(24), secrets.token_urlsafe(32)
53
- expires = self.wall_clock()+1800
54
  self.jobs[ident] = dict(key=key, data=bytearray(data), automatic=automatic,
55
- deadline=self.clock()+1800, expires_at=expires, delivered=False, receipt=None)
56
  return dict(id=ident,key=key,expires_at=expires,automatic=automatic,
57
  sha256=hashlib.sha256(data).hexdigest(),size=len(data))
58
 
 
50
  if len(self.jobs)>=16 or self.retained_bytes+len(data)>self.max_bytes:
51
  raise CapacityExceeded()
52
  ident, key = secrets.token_urlsafe(24), secrets.token_urlsafe(32)
53
+ expires = self.wall_clock()+300
54
  self.jobs[ident] = dict(key=key, data=bytearray(data), automatic=automatic,
55
+ deadline=self.clock()+300, expires_at=expires, delivered=False, receipt=None)
56
  return dict(id=ident,key=key,expires_at=expires,automatic=automatic,
57
  sha256=hashlib.sha256(data).hexdigest(),size=len(data))
58
 
demo.evolution DELETED
Binary file (1 kB)
 
github-simulator/source/Cargo.lock DELETED
@@ -1,792 +0,0 @@
1
- # This file is automatically @generated by Cargo.
2
- # It is not intended for manual editing.
3
- version = 4
4
-
5
- [[package]]
6
- name = "altd_sim"
7
- version = "1.1.0"
8
- dependencies = [
9
- "clap",
10
- "console_error_panic_hook",
11
- "js-sys",
12
- "libc",
13
- "libloading",
14
- "rayon",
15
- "serde",
16
- "serde_json",
17
- "sha2",
18
- "tungstenite",
19
- "wasm-bindgen",
20
- "wasm-bindgen-futures",
21
- "wasm-bindgen-rayon",
22
- "web-sys",
23
- "windows-sys",
24
- ]
25
-
26
- [[package]]
27
- name = "anstream"
28
- version = "1.0.0"
29
- source = "registry+https://github.com/rust-lang/crates.io-index"
30
- checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d"
31
- dependencies = [
32
- "anstyle",
33
- "anstyle-parse",
34
- "anstyle-query",
35
- "anstyle-wincon",
36
- "colorchoice",
37
- "is_terminal_polyfill",
38
- "utf8parse",
39
- ]
40
-
41
- [[package]]
42
- name = "anstyle"
43
- version = "1.0.14"
44
- source = "registry+https://github.com/rust-lang/crates.io-index"
45
- checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000"
46
-
47
- [[package]]
48
- name = "anstyle-parse"
49
- version = "1.0.0"
50
- source = "registry+https://github.com/rust-lang/crates.io-index"
51
- checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e"
52
- dependencies = [
53
- "utf8parse",
54
- ]
55
-
56
- [[package]]
57
- name = "anstyle-query"
58
- version = "1.1.5"
59
- source = "registry+https://github.com/rust-lang/crates.io-index"
60
- checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc"
61
- dependencies = [
62
- "windows-sys",
63
- ]
64
-
65
- [[package]]
66
- name = "anstyle-wincon"
67
- version = "3.0.11"
68
- source = "registry+https://github.com/rust-lang/crates.io-index"
69
- checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d"
70
- dependencies = [
71
- "anstyle",
72
- "once_cell_polyfill",
73
- "windows-sys",
74
- ]
75
-
76
- [[package]]
77
- name = "block-buffer"
78
- version = "0.10.4"
79
- source = "registry+https://github.com/rust-lang/crates.io-index"
80
- checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
81
- dependencies = [
82
- "generic-array",
83
- ]
84
-
85
- [[package]]
86
- name = "block-buffer"
87
- version = "0.12.1"
88
- source = "registry+https://github.com/rust-lang/crates.io-index"
89
- checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa"
90
- dependencies = [
91
- "hybrid-array",
92
- ]
93
-
94
- [[package]]
95
- name = "bumpalo"
96
- version = "3.20.3"
97
- source = "registry+https://github.com/rust-lang/crates.io-index"
98
- checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649"
99
-
100
- [[package]]
101
- name = "bytes"
102
- version = "1.12.1"
103
- source = "registry+https://github.com/rust-lang/crates.io-index"
104
- checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04"
105
-
106
- [[package]]
107
- name = "cfg-if"
108
- version = "1.0.5"
109
- source = "registry+https://github.com/rust-lang/crates.io-index"
110
- checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600"
111
-
112
- [[package]]
113
- name = "chacha20"
114
- version = "0.10.2"
115
- source = "registry+https://github.com/rust-lang/crates.io-index"
116
- checksum = "65c35e4b699c7e15ccbe7ee35c005e4fc0a278d22238a2857e6ce2dadeda1b06"
117
- dependencies = [
118
- "cfg-if",
119
- "cpufeatures 0.3.1",
120
- "rand_core",
121
- ]
122
-
123
- [[package]]
124
- name = "clap"
125
- version = "4.6.7"
126
- source = "registry+https://github.com/rust-lang/crates.io-index"
127
- checksum = "aa8876b300ab35ba921adea3dfd70157a46249b33f95c9084ae5709785478946"
128
- dependencies = [
129
- "clap_builder",
130
- "clap_derive",
131
- ]
132
-
133
- [[package]]
134
- name = "clap_builder"
135
- version = "4.6.7"
136
- source = "registry+https://github.com/rust-lang/crates.io-index"
137
- checksum = "ec0797fb7aeb1406c84efac526901f7ec3ead2124f946b494e72879d4b54704d"
138
- dependencies = [
139
- "anstream",
140
- "anstyle",
141
- "clap_lex",
142
- "strsim",
143
- ]
144
-
145
- [[package]]
146
- name = "clap_derive"
147
- version = "4.6.7"
148
- source = "registry+https://github.com/rust-lang/crates.io-index"
149
- checksum = "f9c751b79415d4e559e3d1fcf128e09e720eb673a06d26cf6f392d37d75b66e0"
150
- dependencies = [
151
- "heck",
152
- "proc-macro2",
153
- "quote",
154
- "syn",
155
- ]
156
-
157
- [[package]]
158
- name = "clap_lex"
159
- version = "1.1.1"
160
- source = "registry+https://github.com/rust-lang/crates.io-index"
161
- checksum = "1c133bc6a41be0d194c306b5506d15e6feeea7b1d6604bd3f8310dfb2ca96486"
162
-
163
- [[package]]
164
- name = "colorchoice"
165
- version = "1.0.5"
166
- source = "registry+https://github.com/rust-lang/crates.io-index"
167
- checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570"
168
-
169
- [[package]]
170
- name = "console_error_panic_hook"
171
- version = "0.1.7"
172
- source = "registry+https://github.com/rust-lang/crates.io-index"
173
- checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc"
174
- dependencies = [
175
- "cfg-if",
176
- "wasm-bindgen",
177
- ]
178
-
179
- [[package]]
180
- name = "const-oid"
181
- version = "0.10.2"
182
- source = "registry+https://github.com/rust-lang/crates.io-index"
183
- checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c"
184
-
185
- [[package]]
186
- name = "cpufeatures"
187
- version = "0.2.17"
188
- source = "registry+https://github.com/rust-lang/crates.io-index"
189
- checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
190
- dependencies = [
191
- "libc",
192
- ]
193
-
194
- [[package]]
195
- name = "cpufeatures"
196
- version = "0.3.1"
197
- source = "registry+https://github.com/rust-lang/crates.io-index"
198
- checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566"
199
- dependencies = [
200
- "libc",
201
- ]
202
-
203
- [[package]]
204
- name = "crossbeam-channel"
205
- version = "0.5.17"
206
- source = "registry+https://github.com/rust-lang/crates.io-index"
207
- checksum = "98b0cc327b5bc766e7fda9c9260cc0fa81b43a8e240440422dff70788e3f9ef1"
208
- dependencies = [
209
- "crossbeam-utils",
210
- ]
211
-
212
- [[package]]
213
- name = "crossbeam-deque"
214
- version = "0.8.8"
215
- source = "registry+https://github.com/rust-lang/crates.io-index"
216
- checksum = "622f3fc73690be383c7214310406f28a90e6edeadc3cea882f9d71e495b9711a"
217
- dependencies = [
218
- "crossbeam-epoch",
219
- "crossbeam-utils",
220
- ]
221
-
222
- [[package]]
223
- name = "crossbeam-epoch"
224
- version = "0.9.21"
225
- source = "registry+https://github.com/rust-lang/crates.io-index"
226
- checksum = "dc74980687109a3b14c72fd458107bf0baa1da1a1a805e178d15501ba9b86d9d"
227
- dependencies = [
228
- "crossbeam-utils",
229
- ]
230
-
231
- [[package]]
232
- name = "crossbeam-utils"
233
- version = "0.8.23"
234
- source = "registry+https://github.com/rust-lang/crates.io-index"
235
- checksum = "a31eee39dddec8330830986fcd7625edb5a24ec90ea038215273bbc3adb08ac6"
236
-
237
- [[package]]
238
- name = "crypto-common"
239
- version = "0.1.7"
240
- source = "registry+https://github.com/rust-lang/crates.io-index"
241
- checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
242
- dependencies = [
243
- "generic-array",
244
- "typenum",
245
- ]
246
-
247
- [[package]]
248
- name = "crypto-common"
249
- version = "0.2.2"
250
- source = "registry+https://github.com/rust-lang/crates.io-index"
251
- checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453"
252
- dependencies = [
253
- "hybrid-array",
254
- ]
255
-
256
- [[package]]
257
- name = "data-encoding"
258
- version = "2.11.1"
259
- source = "registry+https://github.com/rust-lang/crates.io-index"
260
- checksum = "4583a4551df46e2792f82ceeac45e850d2e2d5debba0b91f102385cda5b11f06"
261
-
262
- [[package]]
263
- name = "digest"
264
- version = "0.10.7"
265
- source = "registry+https://github.com/rust-lang/crates.io-index"
266
- checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
267
- dependencies = [
268
- "block-buffer 0.10.4",
269
- "crypto-common 0.1.7",
270
- ]
271
-
272
- [[package]]
273
- name = "digest"
274
- version = "0.11.3"
275
- source = "registry+https://github.com/rust-lang/crates.io-index"
276
- checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2"
277
- dependencies = [
278
- "block-buffer 0.12.1",
279
- "const-oid",
280
- "crypto-common 0.2.2",
281
- ]
282
-
283
- [[package]]
284
- name = "either"
285
- version = "1.18.0"
286
- source = "registry+https://github.com/rust-lang/crates.io-index"
287
- checksum = "252afb9ae5eaa683babdc6a068b3f5726eb19e05070c731f9b2a23a7c3e8ed34"
288
-
289
- [[package]]
290
- name = "equivalent"
291
- version = "1.0.2"
292
- source = "registry+https://github.com/rust-lang/crates.io-index"
293
- checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
294
-
295
- [[package]]
296
- name = "futures-core"
297
- version = "0.3.34"
298
- source = "registry+https://github.com/rust-lang/crates.io-index"
299
- checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e"
300
-
301
- [[package]]
302
- name = "futures-task"
303
- version = "0.3.34"
304
- source = "registry+https://github.com/rust-lang/crates.io-index"
305
- checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd"
306
-
307
- [[package]]
308
- name = "futures-util"
309
- version = "0.3.34"
310
- source = "registry+https://github.com/rust-lang/crates.io-index"
311
- checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc"
312
- dependencies = [
313
- "futures-core",
314
- "futures-task",
315
- "pin-project-lite",
316
- "slab",
317
- ]
318
-
319
- [[package]]
320
- name = "generic-array"
321
- version = "0.14.7"
322
- source = "registry+https://github.com/rust-lang/crates.io-index"
323
- checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
324
- dependencies = [
325
- "typenum",
326
- "version_check",
327
- ]
328
-
329
- [[package]]
330
- name = "getrandom"
331
- version = "0.4.3"
332
- source = "registry+https://github.com/rust-lang/crates.io-index"
333
- checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099"
334
- dependencies = [
335
- "cfg-if",
336
- "libc",
337
- "r-efi",
338
- "rand_core",
339
- ]
340
-
341
- [[package]]
342
- name = "hashbrown"
343
- version = "0.17.1"
344
- source = "registry+https://github.com/rust-lang/crates.io-index"
345
- checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
346
-
347
- [[package]]
348
- name = "heck"
349
- version = "0.5.0"
350
- source = "registry+https://github.com/rust-lang/crates.io-index"
351
- checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
352
-
353
- [[package]]
354
- name = "http"
355
- version = "1.5.0"
356
- source = "registry+https://github.com/rust-lang/crates.io-index"
357
- checksum = "918d3568bebf352712bc2ef3d46a8bcf1a75b373be6539de198e9105cbbf9ce0"
358
- dependencies = [
359
- "bytes",
360
- "itoa",
361
- ]
362
-
363
- [[package]]
364
- name = "httparse"
365
- version = "1.10.1"
366
- source = "registry+https://github.com/rust-lang/crates.io-index"
367
- checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
368
-
369
- [[package]]
370
- name = "hybrid-array"
371
- version = "0.4.15"
372
- source = "registry+https://github.com/rust-lang/crates.io-index"
373
- checksum = "27f864f10dfb56725ce5ce5472bc52252c8f93a4ab86327122cebf62c5f59a17"
374
- dependencies = [
375
- "typenum",
376
- ]
377
-
378
- [[package]]
379
- name = "indexmap"
380
- version = "2.14.2"
381
- source = "registry+https://github.com/rust-lang/crates.io-index"
382
- checksum = "cc4e190f5d26ca7051642629da2c52fc03bde85a03197c99408dcd291734c855"
383
- dependencies = [
384
- "equivalent",
385
- "hashbrown",
386
- ]
387
-
388
- [[package]]
389
- name = "is_terminal_polyfill"
390
- version = "1.70.2"
391
- source = "registry+https://github.com/rust-lang/crates.io-index"
392
- checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695"
393
-
394
- [[package]]
395
- name = "itoa"
396
- version = "1.0.18"
397
- source = "registry+https://github.com/rust-lang/crates.io-index"
398
- checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
399
-
400
- [[package]]
401
- name = "js-sys"
402
- version = "0.3.106"
403
- source = "registry+https://github.com/rust-lang/crates.io-index"
404
- checksum = "7883d941dae510fb2d978fc3fe018c71c9e2892fd38854de3e8b92c2e5ad9cc5"
405
- dependencies = [
406
- "cfg-if",
407
- "futures-util",
408
- "wasm-bindgen",
409
- ]
410
-
411
- [[package]]
412
- name = "libc"
413
- version = "0.2.189"
414
- source = "registry+https://github.com/rust-lang/crates.io-index"
415
- checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
416
-
417
- [[package]]
418
- name = "libloading"
419
- version = "0.9.0"
420
- source = "registry+https://github.com/rust-lang/crates.io-index"
421
- checksum = "754ca22de805bb5744484a5b151a9e1a8e837d5dc232c2d7d8c2e3492edc8b60"
422
- dependencies = [
423
- "cfg-if",
424
- "windows-link",
425
- ]
426
-
427
- [[package]]
428
- name = "log"
429
- version = "0.4.34"
430
- source = "registry+https://github.com/rust-lang/crates.io-index"
431
- checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6"
432
-
433
- [[package]]
434
- name = "memchr"
435
- version = "2.8.3"
436
- source = "registry+https://github.com/rust-lang/crates.io-index"
437
- checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
438
-
439
- [[package]]
440
- name = "once_cell"
441
- version = "1.21.4"
442
- source = "registry+https://github.com/rust-lang/crates.io-index"
443
- checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
444
-
445
- [[package]]
446
- name = "once_cell_polyfill"
447
- version = "1.70.2"
448
- source = "registry+https://github.com/rust-lang/crates.io-index"
449
- checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
450
-
451
- [[package]]
452
- name = "pin-project-lite"
453
- version = "0.2.17"
454
- source = "registry+https://github.com/rust-lang/crates.io-index"
455
- checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
456
-
457
- [[package]]
458
- name = "proc-macro2"
459
- version = "1.0.107"
460
- source = "registry+https://github.com/rust-lang/crates.io-index"
461
- checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
462
- dependencies = [
463
- "unicode-ident",
464
- ]
465
-
466
- [[package]]
467
- name = "quote"
468
- version = "1.0.47"
469
- source = "registry+https://github.com/rust-lang/crates.io-index"
470
- checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
471
- dependencies = [
472
- "proc-macro2",
473
- ]
474
-
475
- [[package]]
476
- name = "r-efi"
477
- version = "6.0.0"
478
- source = "registry+https://github.com/rust-lang/crates.io-index"
479
- checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
480
-
481
- [[package]]
482
- name = "rand"
483
- version = "0.10.3"
484
- source = "registry+https://github.com/rust-lang/crates.io-index"
485
- checksum = "65c9fb96cbc91e3478eaae79a69fcd3f1ae4ad052e471fe6732fff548984b4af"
486
- dependencies = [
487
- "chacha20",
488
- "getrandom",
489
- "rand_core",
490
- ]
491
-
492
- [[package]]
493
- name = "rand_core"
494
- version = "0.10.1"
495
- source = "registry+https://github.com/rust-lang/crates.io-index"
496
- checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69"
497
-
498
- [[package]]
499
- name = "rayon"
500
- version = "1.12.0"
501
- source = "registry+https://github.com/rust-lang/crates.io-index"
502
- checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d"
503
- dependencies = [
504
- "either",
505
- "rayon-core",
506
- "wasm_sync",
507
- ]
508
-
509
- [[package]]
510
- name = "rayon-core"
511
- version = "1.13.0"
512
- source = "registry+https://github.com/rust-lang/crates.io-index"
513
- checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91"
514
- dependencies = [
515
- "crossbeam-deque",
516
- "crossbeam-utils",
517
- "wasm_sync",
518
- ]
519
-
520
- [[package]]
521
- name = "rustversion"
522
- version = "1.0.23"
523
- source = "registry+https://github.com/rust-lang/crates.io-index"
524
- checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f"
525
-
526
- [[package]]
527
- name = "serde"
528
- version = "1.0.229"
529
- source = "registry+https://github.com/rust-lang/crates.io-index"
530
- checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
531
- dependencies = [
532
- "serde_core",
533
- "serde_derive",
534
- ]
535
-
536
- [[package]]
537
- name = "serde_core"
538
- version = "1.0.229"
539
- source = "registry+https://github.com/rust-lang/crates.io-index"
540
- checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48"
541
- dependencies = [
542
- "serde_derive",
543
- ]
544
-
545
- [[package]]
546
- name = "serde_derive"
547
- version = "1.0.229"
548
- source = "registry+https://github.com/rust-lang/crates.io-index"
549
- checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
550
- dependencies = [
551
- "proc-macro2",
552
- "quote",
553
- "syn",
554
- ]
555
-
556
- [[package]]
557
- name = "serde_json"
558
- version = "1.0.151"
559
- source = "registry+https://github.com/rust-lang/crates.io-index"
560
- checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14"
561
- dependencies = [
562
- "indexmap",
563
- "itoa",
564
- "memchr",
565
- "serde",
566
- "serde_core",
567
- "zmij",
568
- ]
569
-
570
- [[package]]
571
- name = "sha1"
572
- version = "0.11.0"
573
- source = "registry+https://github.com/rust-lang/crates.io-index"
574
- checksum = "aacc4cc499359472b4abe1bf11d0b12e688af9a805fa5e3016f9a386dc2d0214"
575
- dependencies = [
576
- "cfg-if",
577
- "cpufeatures 0.3.1",
578
- "digest 0.11.3",
579
- ]
580
-
581
- [[package]]
582
- name = "sha2"
583
- version = "0.10.9"
584
- source = "registry+https://github.com/rust-lang/crates.io-index"
585
- checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
586
- dependencies = [
587
- "cfg-if",
588
- "cpufeatures 0.2.17",
589
- "digest 0.10.7",
590
- ]
591
-
592
- [[package]]
593
- name = "slab"
594
- version = "0.4.12"
595
- source = "registry+https://github.com/rust-lang/crates.io-index"
596
- checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
597
-
598
- [[package]]
599
- name = "strsim"
600
- version = "0.11.1"
601
- source = "registry+https://github.com/rust-lang/crates.io-index"
602
- checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
603
-
604
- [[package]]
605
- name = "syn"
606
- version = "3.0.6"
607
- source = "registry+https://github.com/rust-lang/crates.io-index"
608
- checksum = "8593e8e72159ed2257d083c7a454a85cbf854f37a0966d8d483aff8c8a3ebcee"
609
- dependencies = [
610
- "proc-macro2",
611
- "quote",
612
- "unicode-ident",
613
- ]
614
-
615
- [[package]]
616
- name = "thiserror"
617
- version = "2.0.21"
618
- source = "registry+https://github.com/rust-lang/crates.io-index"
619
- checksum = "09e52cb86a36cede5cb101bf8908837b3e4c6e5e59fe7fd85c23fb56200d189e"
620
- dependencies = [
621
- "thiserror-impl",
622
- ]
623
-
624
- [[package]]
625
- name = "thiserror-impl"
626
- version = "2.0.21"
627
- source = "registry+https://github.com/rust-lang/crates.io-index"
628
- checksum = "fe5197923287db20a58125f0bc85c062f7f2c892de97b18c356f9efb14b28524"
629
- dependencies = [
630
- "proc-macro2",
631
- "quote",
632
- "syn",
633
- ]
634
-
635
- [[package]]
636
- name = "tokio"
637
- version = "1.53.1"
638
- source = "registry+https://github.com/rust-lang/crates.io-index"
639
- checksum = "202caea871b69668250d242070849eb495be178ed697a3e98aebce5bc81a0bed"
640
- dependencies = [
641
- "pin-project-lite",
642
- ]
643
-
644
- [[package]]
645
- name = "tungstenite"
646
- version = "0.30.0"
647
- source = "registry+https://github.com/rust-lang/crates.io-index"
648
- checksum = "e48ac77174b19c110a50ab2128b24215ac9cb40e0e12e093fb602d175c569d22"
649
- dependencies = [
650
- "bytes",
651
- "data-encoding",
652
- "http",
653
- "httparse",
654
- "log",
655
- "rand",
656
- "sha1",
657
- "thiserror",
658
- ]
659
-
660
- [[package]]
661
- name = "typenum"
662
- version = "1.20.1"
663
- source = "registry+https://github.com/rust-lang/crates.io-index"
664
- checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20"
665
-
666
- [[package]]
667
- name = "unicode-ident"
668
- version = "1.0.26"
669
- source = "registry+https://github.com/rust-lang/crates.io-index"
670
- checksum = "d245f478577f809a851594d02313b640fb437e0bb33866753cff937863096954"
671
-
672
- [[package]]
673
- name = "utf8parse"
674
- version = "0.2.2"
675
- source = "registry+https://github.com/rust-lang/crates.io-index"
676
- checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
677
-
678
- [[package]]
679
- name = "version_check"
680
- version = "0.9.5"
681
- source = "registry+https://github.com/rust-lang/crates.io-index"
682
- checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
683
-
684
- [[package]]
685
- name = "wasm-bindgen"
686
- version = "0.2.129"
687
- source = "registry+https://github.com/rust-lang/crates.io-index"
688
- checksum = "9bb54f33acc68fd454578d9820b0bde1a1a3d17aa17bb7b6595806d02886d409"
689
- dependencies = [
690
- "cfg-if",
691
- "once_cell",
692
- "rustversion",
693
- "wasm-bindgen-macro",
694
- "wasm-bindgen-shared",
695
- ]
696
-
697
- [[package]]
698
- name = "wasm-bindgen-futures"
699
- version = "0.4.79"
700
- source = "registry+https://github.com/rust-lang/crates.io-index"
701
- checksum = "3cbab34de2d982e9b48e18d216d04c4a6f641066ff19ffb699980f591ee3610e"
702
- dependencies = [
703
- "js-sys",
704
- "tokio",
705
- "wasm-bindgen",
706
- ]
707
-
708
- [[package]]
709
- name = "wasm-bindgen-macro"
710
- version = "0.2.129"
711
- source = "registry+https://github.com/rust-lang/crates.io-index"
712
- checksum = "2e29d0c35b16e224a7eeb5cd2d25e3e1968fbd65604117b44d3b789d00ee8535"
713
- dependencies = [
714
- "quote",
715
- "wasm-bindgen-macro-support",
716
- ]
717
-
718
- [[package]]
719
- name = "wasm-bindgen-macro-support"
720
- version = "0.2.129"
721
- source = "registry+https://github.com/rust-lang/crates.io-index"
722
- checksum = "6f501a8bc3719dba86ef8ae4728879c08001bea749eb1333ac5b91e040e2a6b7"
723
- dependencies = [
724
- "bumpalo",
725
- "proc-macro2",
726
- "quote",
727
- "syn",
728
- "wasm-bindgen-shared",
729
- ]
730
-
731
- [[package]]
732
- name = "wasm-bindgen-rayon"
733
- version = "1.3.0"
734
- source = "registry+https://github.com/rust-lang/crates.io-index"
735
- checksum = "9a16c60a56c81e4dc3b9c43d76ba5633e1c0278211d59a9cb07d61b6cd1c6583"
736
- dependencies = [
737
- "crossbeam-channel",
738
- "js-sys",
739
- "rayon",
740
- "wasm-bindgen",
741
- ]
742
-
743
- [[package]]
744
- name = "wasm-bindgen-shared"
745
- version = "0.2.129"
746
- source = "registry+https://github.com/rust-lang/crates.io-index"
747
- checksum = "23f0c9c52aa7cd7d77769a4cfe2a9adb1b331f489a41d912ce14513d5ab995c6"
748
- dependencies = [
749
- "unicode-ident",
750
- ]
751
-
752
- [[package]]
753
- name = "wasm_sync"
754
- version = "0.1.2"
755
- source = "registry+https://github.com/rust-lang/crates.io-index"
756
- checksum = "cff360cade7fec41ff0e9d2cda57fe58258c5f16def0e21302394659e6bbb0ea"
757
- dependencies = [
758
- "js-sys",
759
- "wasm-bindgen",
760
- "web-sys",
761
- ]
762
-
763
- [[package]]
764
- name = "web-sys"
765
- version = "0.3.106"
766
- source = "registry+https://github.com/rust-lang/crates.io-index"
767
- checksum = "88261b9deccee56594c11a3460c462c41f58d148598fe70ad77070126a68aba4"
768
- dependencies = [
769
- "js-sys",
770
- "wasm-bindgen",
771
- ]
772
-
773
- [[package]]
774
- name = "windows-link"
775
- version = "0.2.1"
776
- source = "registry+https://github.com/rust-lang/crates.io-index"
777
- checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
778
-
779
- [[package]]
780
- name = "windows-sys"
781
- version = "0.61.2"
782
- source = "registry+https://github.com/rust-lang/crates.io-index"
783
- checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
784
- dependencies = [
785
- "windows-link",
786
- ]
787
-
788
- [[package]]
789
- name = "zmij"
790
- version = "1.0.23"
791
- source = "registry+https://github.com/rust-lang/crates.io-index"
792
- checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
github-simulator/source/Cargo.toml DELETED
@@ -1,77 +0,0 @@
1
- [package]
2
- name = "altd_sim"
3
- version = "1.1.0"
4
- edition = "2021"
5
- description = "CPU game-fidelity simulator and trainer for AI Learns To Drive"
6
- license = "MIT"
7
- repository = "https://github.com/Zorro909/driving_sim_rs"
8
- readme = "README.md"
9
- keywords = ["simulation", "driving", "training", "neural-network", "wasm"]
10
- categories = ["simulation", "science", "command-line-utilities"]
11
- rust-version = "1.93"
12
- exclude = ["tests/fixtures/", "wasm/test/"]
13
-
14
- [lib]
15
- # Keep native test artifacts distinct. wasm/build.sh selects cdylib explicitly.
16
- crate-type = ["rlib"]
17
-
18
- [features]
19
- default = ["cli", "server"]
20
- # The `altd-sim` command line (native only).
21
- cli = ["dep:clap"]
22
- # `altd-sim serve`: the WebSocket server Drive Lab can train on (native only).
23
- server = ["cli", "dep:tungstenite"]
24
- # The WebAssembly library in src/wasm: JavaScript bindings and the WebGPU raycaster.
25
- wasm = ["dep:wasm-bindgen", "dep:js-sys", "dep:wasm-bindgen-futures", "dep:web-sys", "dep:console_error_panic_hook"]
26
- wasm-threads = ["wasm", "dep:wasm-bindgen-rayon"]
27
- # Browser integration diagnostics, excluded from distributed packages.
28
- wasm-thread-test = ["wasm"]
29
-
30
- [dependencies]
31
- clap = { version = "4", features = ["derive"], optional = true }
32
- rayon = "1"
33
- serde = { version = "1", features = ["derive"] }
34
- # float_roundtrip parses JSON floats exactly like Python's float().
35
- serde_json = { version = "1", features = ["float_roundtrip", "preserve_order"] }
36
- wasm-bindgen = { version = "0.2", optional = true }
37
- js-sys = { version = "0.3", optional = true }
38
- wasm-bindgen-futures = { version = "0.4", optional = true }
39
- console_error_panic_hook = { version = "0.1", optional = true }
40
- web-sys = { version = "0.3", optional = true, features = [
41
- "Window", "Navigator", "WorkerGlobalScope", "WorkerNavigator",
42
- "Gpu", "GpuAdapter", "GpuDevice", "GpuQueue",
43
- "GpuBuffer", "GpuBufferDescriptor", "GpuBufferBinding",
44
- "GpuShaderModule", "GpuShaderModuleDescriptor", "GpuCompilationInfo", "GpuCompilationMessage", "GpuCompilationMessageType",
45
- "GpuComputePipeline", "GpuComputePipelineDescriptor", "GpuProgrammableStage", "GpuPipelineLayout",
46
- "GpuBindGroup", "GpuBindGroupDescriptor", "GpuBindGroupEntry", "GpuBindGroupLayout",
47
- "GpuCommandEncoder", "GpuComputePassEncoder", "GpuCommandBuffer",
48
- "gpu_buffer_usage", "gpu_map_mode",
49
- ] }
50
-
51
- [target.'cfg(not(target_arch = "wasm32"))'.dependencies]
52
- # Runtime loading of the HIP simulator (src/gpu/hip.rs).
53
- libloading = "0.9"
54
- sha2 = "0.10"
55
- # Synchronous WebSockets for `altd-sim serve`, without TLS.
56
- tungstenite = { version = "0.30", default-features = false, features = ["handshake"], optional = true }
57
-
58
- # Process statistics in the CLI (src/bin/altd-sim/platform.rs).
59
- [target.'cfg(unix)'.dependencies]
60
- libc = "0.2"
61
-
62
- [target.'cfg(windows)'.dependencies]
63
- windows-sys = { version = "0.61", features = ["Wdk_System_SystemServices", "Win32_Foundation", "Win32_System_ProcessStatus", "Win32_System_SystemInformation", "Win32_System_Threading"] }
64
-
65
- [target.'cfg(target_arch = "wasm32")'.dependencies]
66
- wasm-bindgen-rayon = { version = "=1.3.0", optional = true, features = ["no-bundler"] }
67
-
68
- [profile.release]
69
- codegen-units = 1
70
- lto = "fat"
71
- panic = "abort"
72
- debug = "line-tables-only"
73
-
74
- [[bin]]
75
- name = "altd-sim"
76
- path = "src/bin/altd-sim/main.rs"
77
- required-features = ["cli"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
github-simulator/source/GODOT_LICENSE DELETED
@@ -1,43 +0,0 @@
1
- Godot Engine source adaptations in src/physics/broadphase.rs
2
-
3
- Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md).
4
- Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur.
5
-
6
- Permission is hereby granted, free of charge, to any person obtaining
7
- a copy of this software and associated documentation files (the
8
- "Software"), to deal in the Software without restriction, including
9
- without limitation the rights to use, copy, modify, merge, publish,
10
- distribute, sublicense, and/or sell copies of the Software, and to
11
- permit persons to whom the Software is furnished to do so, subject to
12
- the following conditions:
13
- The above copyright notice and this permission notice shall be
14
- included in all copies or substantial portions of the Software.
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18
- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19
- CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20
- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21
- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
-
23
- Modified tree-balancing algorithm, originally Randy Gaul qu3e:
24
- /**
25
- * @file q3DynamicAABBTree.h
26
- * @author Randy Gaul
27
- * @date 10/10/2014
28
- * Copyright (c) 2014 Randy Gaul http://www.randygaul.net
29
- * This software is provided 'as-is', without any express or implied
30
- * warranty. In no event will the authors be held liable for any damages
31
- * arising from the use of this software.
32
- * Permission is granted to anyone to use this software for any purpose,
33
- * including commercial applications, and to alter it and redistribute it
34
- * freely, subject to the following restrictions:
35
- * 1. The origin of this software must not be misrepresented; you must not
36
- * claim that you wrote the original software. If you use this software
37
- * in a product, an acknowledgment in the product documentation would be
38
- * appreciated but is not required.
39
- * 2. Altered source versions must be plainly marked as such, and must not
40
- * be misrepresented as being the original software.
41
- * 3. This notice may not be removed or altered from any source distribution.
42
- */
43
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
github-simulator/source/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 Zorro909
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
github-simulator/source/README.md DELETED
@@ -1,183 +0,0 @@
1
- # altd-sim
2
-
3
- [![CI](https://github.com/Zorro909/driving_sim_rs/actions/workflows/ci.yml/badge.svg)](https://github.com/Zorro909/driving_sim_rs/actions/workflows/ci.yml)
4
-
5
- `altd-sim` is a Rust vehicle simulator and neural-network trainer for AI Learns To Drive. It runs headless on the CPU, through a runtime-loaded AMD HIP library, or in WebAssembly. It reproduces the game's floating-point arithmetic, contact ordering, sensors and evolution behavior against captured regression fixtures. Exactness claims apply to the tested inputs; [fidelity](docs/fidelity.md) records the limits.
6
-
7
- The repository includes vehicle and sensor templates, tile resources, fixed generated tracks and self-contained tests. Campaign tracks are not distributed.
8
-
9
- ## Getting started
10
-
11
- This guide sets up `altd-sim serve`, the local simulator for [Drive Lab](https://drivinglab.jectrum.de). Drive Lab keeps your tracks, runs and downloads in the browser; the server drives the cars on your CPU threads or an AMD GPU. That removes the browser's limits on cars and network size and its eight-thread cap.
12
-
13
- ### 1. Download
14
-
15
- Download the archive for your system from [Releases](https://github.com/Zorro909/driving_sim_rs/releases). Tagged versions are stable; the `nightly` pre-release is rebuilt from every push to `main` and keeps the same file names. `SHA256SUMS` lists the archive checksums.
16
-
17
- | System | Archive | Training on |
18
- | --- | --- | --- |
19
- | Linux x86_64 | `altd-sim-<version>-x86_64-unknown-linux-gnu.tar.gz` | CPU, or AMD GPU through HIP |
20
- | Windows x86_64 | `altd-sim-<version>-x86_64-pc-windows-msvc.zip` | CPU |
21
- | macOS, Apple silicon | `altd-sim-<version>-aarch64-apple-darwin.tar.gz` | CPU |
22
-
23
- Unpack it and open a terminal in the unpacked folder:
24
-
25
- ```sh
26
- tar -xzf altd-sim-nightly-x86_64-unknown-linux-gnu.tar.gz
27
- cd altd-sim-nightly-x86_64-unknown-linux-gnu
28
- ./altd-sim --version
29
- ```
30
-
31
- On Windows, extract the `.zip`, then open PowerShell in the folder and use `.\altd-sim.exe` wherever this guide says `./altd-sim`. macOS binaries are unsigned, so first remove the download quarantine with `xattr -d com.apple.quarantine altd-sim`. Apple silicon uses the portable trigonometry described in [fidelity](docs/fidelity.md).
32
-
33
- ### 2. Start the server
34
-
35
- ```sh
36
- ./altd-sim serve
37
- ```
38
-
39
- ```text
40
- altd-sim serve: listening on ws://127.0.0.1:47800/v1
41
- allowed origins: https://drivinglab.jectrum.de
42
- CPU threads: 16
43
- HIP: available (AMD Radeon RX 7900 XTX)
44
- ```
45
-
46
- Keep the terminal open while you train; <kbd>Ctrl</kbd>+<kbd>C</kbd> stops the server. It listens only on `127.0.0.1`, so the browser must run on the same computer.
47
-
48
- ### 3. Connect Drive Lab
49
-
50
- 1. In Drive Lab, open **New run**. Under **Compute**, enable **Use a local altd-sim**. The port field defaults to 47800.
51
- 2. If the browser asks to allow access to devices on your local network, allow it.
52
- 3. The status shows the connection, the CPU thread count and the GPU, if HIP is available. Choose **Native CPU** or **Native GPU (HIP)** and start the run.
53
-
54
- Each browser connection gets its own session. Only one session at a time can use the GPU; another one asking for HIP trains on CPU and says why. If the server stops during training, the run stops and keeps its last saved generation. Start the server again and resume the run.
55
-
56
- ### Options
57
-
58
- | Option | Use it to |
59
- | --- | --- |
60
- | `--threads N` | Limit the CPU threads, for example to keep the computer responsive. The default is every logical CPU the process may use. |
61
- | `--math-profile PROFILE` | Reproduce `proton`, `win10-fma3` or `win11-fma3` arithmetic. The default follows the server's operating system; clients can select a profile for each session. |
62
- | `--port N` | Listen on another port when 47800 is taken. Set the same port in Drive Lab. |
63
- | `--allow-origin ORIGIN` | Allow another Drive Lab address, such as a development copy: `--allow-origin http://127.0.0.1:5173`. It replaces the default; repeat the option to allow several. |
64
-
65
- ```sh
66
- ./altd-sim serve --threads 8 --port 47801
67
- ```
68
-
69
- All builds include all three math profiles. Windows 11 24H2 and newer default to `win11-fma3`; earlier Windows releases use `win10-fma3`; Linux and macOS use `proton`. To train on Linux for a game running on current Windows, for example, pass `--math-profile win11-fma3`. Checkpoints retain their profile. [Math profiles](math/README.md) describes the kernels and captured reference data.
70
-
71
- ### Training on an AMD GPU
72
-
73
- The Linux archive contains `libaltd_gpu.so` next to `altd-sim`. It needs a ROCm 7.x runtime and one of the [covered GPU architectures](gpu/README.md). `./altd-sim gpu-info` checks that the library loads and prints `"layout": "ok"`; with a GPU present it also runs one kernel and prints the device, and fails if the library has no code for that GPU; the server's `HIP:` line shows the device or why HIP is unavailable.
74
-
75
- A HIP session drives its first 12 ticks on both the GPU and the CPU and compares them. If they differ, or the network or track needs something HIP does not support, the session trains on CPU and Drive Lab shows the reason. Native CPU and HIP produce the same results. Browser training can differ from both in the last digits of a few values ([issue #3](https://github.com/Zorro909/driving_sim_rs/issues/3)), so a run moved between the browser and the server can develop differently from then on.
76
-
77
- NVIDIA GPUs use the same backend: build the library with `gpu/build-cuda.sh` (Linux) or `gpu/build-cuda.ps1` (Windows) as described in the [GPU guide](gpu/README.md#nvidia-cuda). The release archives do not include it.
78
-
79
- ### Troubleshooting
80
-
81
- - **`cannot listen on 127.0.0.1:47800: Address already in use`**: another server is already running, or another program uses the port. Stop it or choose another `--port`.
82
- - **Drive Lab cannot connect**: check that the server is running and that both use the same port. A Drive Lab address other than `https://drivinglab.jectrum.de` must be allowed with `--allow-origin`, including its scheme and port. If you denied local network access, allow it again in the browser's site settings.
83
- - **`HIP: unavailable`**: the line gives the reason. `./altd-sim gpu-info` reports library problems, and [GPU setup](gpu/README.md) covers ROCm and other GPU architectures.
84
-
85
- [Server documentation](docs/server.md) describes the protocol and its security checks for other clients.
86
-
87
- ### Training without Drive Lab
88
-
89
- The CLI can also train on its own. This example trains Rally networks on generated tracks and writes them to `runs/example`:
90
-
91
- ```sh
92
- ./altd-sim train-scratch --scene assets/scenes/rally_template.json --track-mode random \
93
- --random-track-settings assets/random_track_settings.json \
94
- --population 256 --generations 3 --ticks 600 --out-dir runs/example
95
- ```
96
-
97
- Add `--gpu` to train on an AMD GPU. `./altd-sim --help` lists every command, and the [CLI reference](docs/cli.md) describes their inputs and outputs.
98
-
99
- ## Build from source
100
-
101
- Rust 1.94 or newer is the tested native toolchain. Build from the repository root. `--offline` works when dependencies are already cached; omit it on the first build if needed.
102
-
103
- ```sh
104
- cargo build --release --offline
105
- python3 tools/benchmark.py --population 1024 --ticks 600 --repeats 5 \
106
- --report target/benchmark.json
107
-
108
- target/release/altd-sim --threads 8 train-scratch \
109
- --scene assets/scenes/rally_template.json --track-mode random \
110
- --random-track-settings assets/random_track_settings.json \
111
- --population 256 --generations 3 --ticks 600 --seed 1729 \
112
- --eliminate-on-wall --idle-eliminate --save-final-candidate \
113
- --out-dir runs/example
114
- ```
115
-
116
- The training command starts Xavier networks and generates a reproducible track each generation. Increase the population, generations and tick limit for longer runs. Supply the same scene and track settings when resuming, with `--resume` and a higher `--generations` target.
117
-
118
- `.cargo/config.toml` uses `target-cpu=native` for x86 local builds, including the published CPU measurements. For a portable x86_64 binary, override it explicitly:
119
-
120
- ```sh
121
- RUSTFLAGS='-C target-cpu=x86-64' cargo build --release --offline
122
- ```
123
-
124
- AVX2 network and geometry paths use runtime detection and retain scalar fallbacks. Exact native trigonometry uses x87 on x86; other targets use the portable implementation described in the fidelity notes.
125
-
126
- ## Other backends
127
-
128
- AMD GPU builds need ROCm and `hipcc`. The default architecture is `gfx1100`, for the RX 7900 XTX.
129
-
130
- ```sh
131
- gpu/build.sh
132
- # Add --gpu to the train-scratch command above.
133
- ```
134
-
135
- For other AMD GPUs, set `GPU_ARCH` to one or more architectures when building. Rust builds do not require ROCm. See [GPU setup](gpu/README.md) for validation and profiling.
136
-
137
- The default build also includes a local WebSocket server for native CPU or HIP sessions:
138
-
139
- ```sh
140
- target/release/altd-sim --threads 8 serve
141
- ```
142
-
143
- [Getting started](#getting-started) explains its options and how to connect Drive Lab; [server documentation](docs/server.md) covers the protocol, security checks and checkpoint resume.
144
-
145
- WebAssembly builds need the wasm32 target and the matching `wasm-bindgen` CLI:
146
-
147
- ```sh
148
- rustup target add wasm32-unknown-unknown
149
- cargo install wasm-bindgen-cli --version "$(wasm/bindgen-version.sh)" --locked
150
- wasm/build.sh
151
- ```
152
-
153
- The JavaScript library includes CPU simulation, a threaded CPU package and optional WebGPU backends. See [WASM setup](wasm/README.md) for initialization, browser requirements and tests. Expanded native/WASM comparisons have known last-bit differences; serial and threaded WASM are compared separately.
154
-
155
- ## CLI and output
156
-
157
- `target/release/altd-sim --help` and `target/release/altd-sim COMMAND --help` show arguments. `bench` measures a fixed population; `train` evolves an exported network; `train-scratch` starts Xavier networks and supports checkpoints, generated-track batches and stop conditions; `evaluate` runs a frozen candidate against a hash-validated suite; `serve` exposes sessions over a loopback WebSocket. The `compare-*` commands compare user-supplied captures with the simulator. Scenes and recorded traces are explicit inputs. [CLI reference](docs/cli.md) covers defaults, resume behavior and report formats.
158
-
159
- A `train-scratch` run writes:
160
-
161
- | File | Contents |
162
- | --- | --- |
163
- | `run.json`, `log.jsonl`, `progress.json` | Effective options, completed generations and current progress |
164
- | `checkpoint.json`, `checkpoint_gNNNNN.bin` | Generation-boundary population and RNG state |
165
- | `best.json`, `best_laps/` | Networks that set a new best lap |
166
- | `candidate.json` | Final fitness leader when `--save-final-candidate` is enabled |
167
- | `tracks/` | Generated track geometry for replay |
168
-
169
- ## Code and tests
170
-
171
- `src/math/` contains runtime-compatible arithmetic and vectors. `src/physics/` implements vehicles and contacts, while `src/track/` owns scene geometry, spatial queries and generated tracks. `src/nn/` provides scalar and AVX2 inference. `src/training/` owns populations, evolution, RNGs, evaluation and embedding sessions. `src/gpu/hip.rs` loads HIP; `src/gpu/simulation.rs` shares device layouts with `src/wasm/`, which supplies JavaScript and WebGPU bindings. The CLI entrypoint is `src/bin/altd-sim/main.rs`, beside its argument, comparison, benchmark and checkpoint modules. Rust imports follow these groups, such as `altd_sim::physics::car::Car` and `altd_sim::training::session::Session`. See [design notes](docs/design.md).
172
-
173
- ```sh
174
- cargo test --release --offline
175
- cargo test --offline
176
- cargo build --offline --target wasm32-unknown-unknown --no-default-features --features wasm
177
- ```
178
-
179
- Tests retain self-contained native captures and label generated golden data as current-code regressions. Browser integration checks live in `wasm/test/`; HIP equivalence checks use `gpu_check`. The exhaustive trigonometry scan and hardware-dependent tests are opt-in. See [performance](docs/performance.md), [GPU internals](docs/gpu.md) and [WASM fidelity](docs/wasm.md).
180
-
181
- GitHub Actions checks formatting, native and WASM Clippy, native release and debug tests, Windows and macOS Clippy and release tests, the HIP library build and layout, rustdoc, Rust 1.93 compatibility, and WASM packages with CPU browser comparisons. The release workflow builds and smoke-tests the archives, then publishes tags and nightly builds. Its native jobs override `target-cpu=native` with `x86-64` and include the flags in their cache keys, so cached builds can move between runner CPUs. Serial/threaded browser tests retain the documented expanded native differences. HIP equivalence and hardware WebGPU checks run separately because the hosted runners have no GPU.
182
-
183
- The project uses the [MIT license](LICENSE). Godot-derived code retains the [Godot notice](GODOT_LICENSE), and numerical modules retain their source notices.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
github-simulator/source/assets/models/formula.json DELETED
@@ -1,73 +0,0 @@
1
- {
2
- "vehicle_type": "formula",
3
- "vision": [
4
- {
5
- "angle": -135,
6
- "length": 624.2640380859375
7
- },
8
- {
9
- "angle": -90,
10
- "length": 200.00003051757812
11
- },
12
- {
13
- "angle": -60,
14
- "length": 499.9999694824219
15
- },
16
- {
17
- "angle": -35,
18
- "length": 691.4912109375
19
- },
20
- {
21
- "angle": -20,
22
- "length": 763.8155517578125
23
- },
24
- {
25
- "angle": -10,
26
- "length": 790.8846435546875
27
- },
28
- {
29
- "angle": 0,
30
- "length": 800
31
- },
32
- {
33
- "angle": 10,
34
- "length": 790.8846435546875
35
- },
36
- {
37
- "angle": 20,
38
- "length": 763.8155517578125
39
- },
40
- {
41
- "angle": 35,
42
- "length": 691.4912109375
43
- },
44
- {
45
- "angle": 60,
46
- "length": 499.9999694824219
47
- },
48
- {
49
- "angle": 90,
50
- "length": 200.00003051757812
51
- },
52
- {
53
- "angle": 135,
54
- "length": 624.2640380859375
55
- }
56
- ],
57
- "sensors": [
58
- "angular_velocity",
59
- "boost_capacity",
60
- "wheel_angle",
61
- "grip",
62
- "velocity_front",
63
- "velocity_side",
64
- "track_curvature"
65
- ],
66
- "outputs": [
67
- "steering",
68
- "acceleration",
69
- "handbrake",
70
- "brake",
71
- "boost"
72
- ]
73
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
github-simulator/source/assets/models/rally.json DELETED
@@ -1,74 +0,0 @@
1
- {
2
- "vehicle_type": "rally",
3
- "vision": [
4
- {
5
- "angle": -135,
6
- "length": 624.2640380859375
7
- },
8
- {
9
- "angle": -90,
10
- "length": 200.00003051757812
11
- },
12
- {
13
- "angle": -60,
14
- "length": 499.9999694824219
15
- },
16
- {
17
- "angle": -35,
18
- "length": 691.4912109375
19
- },
20
- {
21
- "angle": -20,
22
- "length": 763.8155517578125
23
- },
24
- {
25
- "angle": -10,
26
- "length": 790.8846435546875
27
- },
28
- {
29
- "angle": 0,
30
- "length": 800
31
- },
32
- {
33
- "angle": 10,
34
- "length": 790.8846435546875
35
- },
36
- {
37
- "angle": 20,
38
- "length": 763.8155517578125
39
- },
40
- {
41
- "angle": 35,
42
- "length": 691.4912109375
43
- },
44
- {
45
- "angle": 60,
46
- "length": 499.9999694824219
47
- },
48
- {
49
- "angle": 90,
50
- "length": 200.00003051757812
51
- },
52
- {
53
- "angle": 135,
54
- "length": 624.2640380859375
55
- }
56
- ],
57
- "sensors": [
58
- "angular_velocity",
59
- "boost_capacity",
60
- "correct_direction",
61
- "grip",
62
- "velocity_front",
63
- "velocity_side",
64
- "track_curvature"
65
- ],
66
- "outputs": [
67
- "steering",
68
- "acceleration",
69
- "handbrake",
70
- "brake",
71
- "boost"
72
- ],
73
- "fidelity_provenance": "Sensor lengths retain the captured single-precision values."
74
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
github-simulator/source/assets/networks/formula.json DELETED
@@ -1,31 +0,0 @@
1
- {
2
- "inputs": [
3
- "↑ -135°",
4
- "↑ -90°",
5
- "↑ -60°",
6
- "↑ -35°",
7
- "↑ -20°",
8
- "↑ -10°",
9
- "↑ 0°",
10
- "↑ 10°",
11
- "↑ 20°",
12
- "↑ 35°",
13
- "↑ 60°",
14
- "↑ 90°",
15
- "↑ 135°",
16
- "AngVel",
17
- "Boost",
18
- "Wheel",
19
- "Grip",
20
- "VelF",
21
- "VelS",
22
- "Curve"
23
- ],
24
- "outputs": [
25
- "Steering",
26
- "Acceleration",
27
- "Handbrake",
28
- "Brake",
29
- "Boost"
30
- ]
31
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
github-simulator/source/assets/networks/rally.json DELETED
@@ -1,31 +0,0 @@
1
- {
2
- "inputs": [
3
- "↑ -135°",
4
- "↑ -90°",
5
- "↑ -60°",
6
- "↑ -35°",
7
- "↑ -20°",
8
- "↑ -10°",
9
- "↑ 0°",
10
- "↑ 10°",
11
- "↑ 20°",
12
- "↑ 35°",
13
- "↑ 60°",
14
- "↑ 90°",
15
- "↑ 135°",
16
- "AngVel",
17
- "Boost",
18
- "Dir",
19
- "Grip",
20
- "VelF",
21
- "VelS",
22
- "Curve"
23
- ],
24
- "outputs": [
25
- "Steering",
26
- "Acceleration",
27
- "Handbrake",
28
- "Brake",
29
- "Boost"
30
- ]
31
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
github-simulator/source/assets/random_track_settings.json DELETED
@@ -1,7 +0,0 @@
1
- {
2
- "length": { "min": 12, "max": 40 },
3
- "allow_double": [false, true],
4
- "surfaces": { "pool": [0, 1, 2], "count": [1, 2, 3] },
5
- "distribution": [0, 1],
6
- "start": null
7
- }
 
 
 
 
 
 
 
 
github-simulator/source/assets/scenes/formula_template.json DELETED
@@ -1,111 +0,0 @@
1
- {
2
- "vehicle": {
3
- "type": "Formula",
4
- "mass": 2,
5
- "inertia_property": 0,
6
- "inertia_server": 1038.1666259765625,
7
- "shape_size": [
8
- 73,
9
- 30
10
- ],
11
- "shape_position": [
12
- 0,
13
- 0
14
- ],
15
- "shape_rotation": 1.5708,
16
- "gravity_scale": 1,
17
- "linear_damp": 0,
18
- "angular_damp": 0,
19
- "max_contacts_reported": 4,
20
- "friction": 0.95,
21
- "bounce": 0.1,
22
- "grip": 2,
23
- "steering_speed": 0.4000000059604645,
24
- "center_steering": true,
25
- "air_resistance": 0.10000000149011612,
26
- "max_velocity": 1200,
27
- "surfaces": {
28
- "asphalt": {
29
- "grip": 1,
30
- "power": 1,
31
- "steering": 1
32
- },
33
- "dirt": {
34
- "grip": 0.8,
35
- "power": 0.5,
36
- "steering": 1
37
- },
38
- "ice": {
39
- "grip": 0.3,
40
- "power": 0.5,
41
- "steering": 1
42
- }
43
- },
44
- "wheels": [
45
- {
46
- "position": [
47
- -11,
48
- -17
49
- ],
50
- "steering": true,
51
- "max_angle_deg": 35,
52
- "power": 0,
53
- "brake_power": 3.5,
54
- "handbrake_power": 0
55
- },
56
- {
57
- "position": [
58
- 11,
59
- -17
60
- ],
61
- "steering": true,
62
- "max_angle_deg": 35,
63
- "power": 0,
64
- "brake_power": 3.5,
65
- "handbrake_power": 0
66
- },
67
- {
68
- "position": [
69
- -13,
70
- 29
71
- ],
72
- "steering": false,
73
- "max_angle_deg": 0,
74
- "power": 6,
75
- "brake_power": 3,
76
- "handbrake_power": 3
77
- },
78
- {
79
- "position": [
80
- 13,
81
- 29
82
- ],
83
- "steering": false,
84
- "max_angle_deg": 0,
85
- "power": 6,
86
- "brake_power": 3,
87
- "handbrake_power": 3
88
- }
89
- ]
90
- },
91
- "physics": {
92
- "real_precision": "single",
93
- "contact_recycle_radius": 1,
94
- "contact_max_separation": 1.5,
95
- "contact_max_allowed_penetration": 0.3,
96
- "contact_default_bias": 0.8,
97
- "solver_iterations": 16
98
- },
99
- "track": {
100
- "name": "Generated track template",
101
- "tiles": [],
102
- "path": [],
103
- "walls": [],
104
- "physics_shapes": []
105
- },
106
- "reset_position": [
107
- 0,
108
- 0
109
- ],
110
- "reset_rotation": 0
111
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
github-simulator/source/assets/scenes/rally_template.json DELETED
@@ -1,112 +0,0 @@
1
- {
2
- "vehicle": {
3
- "type": "Rally",
4
- "mass": 3,
5
- "inertia_property": 0,
6
- "inertia_server": 1171.25,
7
- "shape_size": [
8
- 62,
9
- 29
10
- ],
11
- "shape_position": [
12
- 0,
13
- 0
14
- ],
15
- "shape_rotation": 1.5708,
16
- "gravity_scale": 1,
17
- "linear_damp": 0,
18
- "angular_damp": 0,
19
- "max_contacts_reported": 4,
20
- "continuous_cd": "Disabled",
21
- "friction": 0.95,
22
- "bounce": 0.1,
23
- "grip": 2.25,
24
- "steering_speed": 0.4000000059604645,
25
- "center_steering": true,
26
- "air_resistance": 0.15,
27
- "max_velocity": 1000,
28
- "surfaces": {
29
- "asphalt": {
30
- "grip": 1,
31
- "power": 0.77,
32
- "steering": 1
33
- },
34
- "dirt": {
35
- "grip": 0.9,
36
- "power": 0.82,
37
- "steering": 1
38
- },
39
- "ice": {
40
- "grip": 0.42,
41
- "power": 0.6,
42
- "steering": 1
43
- }
44
- },
45
- "wheels": [
46
- {
47
- "position": [
48
- -14,
49
- -24
50
- ],
51
- "steering": true,
52
- "max_angle_deg": 35,
53
- "power": 2.5,
54
- "brake_power": 3.5,
55
- "handbrake_power": 0
56
- },
57
- {
58
- "position": [
59
- 14,
60
- -24
61
- ],
62
- "steering": true,
63
- "max_angle_deg": 35,
64
- "power": 2.5,
65
- "brake_power": 3.5,
66
- "handbrake_power": 0
67
- },
68
- {
69
- "position": [
70
- -14,
71
- 24
72
- ],
73
- "steering": false,
74
- "max_angle_deg": 0,
75
- "power": 3.5,
76
- "brake_power": 0,
77
- "handbrake_power": 0
78
- },
79
- {
80
- "position": [
81
- 14,
82
- 24
83
- ],
84
- "steering": false,
85
- "max_angle_deg": 0,
86
- "power": 3.5,
87
- "brake_power": 0,
88
- "handbrake_power": 0
89
- }
90
- ]
91
- },
92
- "physics": {
93
- "real_precision": "single",
94
- "contact_recycle_radius": 1,
95
- "contact_max_separation": 1.5,
96
- "contact_max_allowed_penetration": 0.3,
97
- "contact_default_bias": 0.8,
98
- "solver_iterations": 16
99
- },
100
- "track": {
101
- "name": "Generated track template",
102
- "tiles": [],
103
- "path": [],
104
- "walls": [],
105
- "physics_shapes": []
106
- },
107
- "reset_position": [
108
- 0,
109
- 0
110
- ],
111
- "reset_rotation": 0
112
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
github-simulator/source/assets/scenes/snowmobile_template.json DELETED
@@ -1,123 +0,0 @@
1
- {
2
- "vehicle": {
3
- "type": "Snowmobile",
4
- "mass": 1.5,
5
- "inertia_property": 0,
6
- "inertia_server": 552.625732421875,
7
- "shape_size": [
8
- 65,
9
- 14.0002
10
- ],
11
- "shape_position": [
12
- -0.000114441,
13
- 0.499986
14
- ],
15
- "shape_rotation": 1.5708,
16
- "gravity_scale": 1,
17
- "linear_damp": 0,
18
- "angular_damp": 0,
19
- "max_contacts_reported": 4,
20
- "continuous_cd": "Disabled",
21
- "friction": 0.95,
22
- "bounce": 0.1,
23
- "grip": 2,
24
- "steering_speed": 0.2,
25
- "center_steering": true,
26
- "air_resistance": 0.3,
27
- "max_velocity": 600,
28
- "surfaces": {
29
- "asphalt": {
30
- "grip": 0.9,
31
- "power": 0.9,
32
- "steering": 0.25
33
- },
34
- "dirt": {
35
- "grip": 0.7,
36
- "power": 0.8,
37
- "steering": 0.7
38
- },
39
- "ice": {
40
- "grip": 0.4,
41
- "power": 0.8,
42
- "steering": 0.7
43
- }
44
- },
45
- "wheels": [
46
- {
47
- "position": [
48
- -10,
49
- -25
50
- ],
51
- "steering": true,
52
- "max_angle_deg": 35,
53
- "power": 0,
54
- "brake_power": 0,
55
- "handbrake_power": 0
56
- },
57
- {
58
- "position": [
59
- 10,
60
- -25
61
- ],
62
- "steering": true,
63
- "max_angle_deg": 35,
64
- "power": 0,
65
- "brake_power": 0,
66
- "handbrake_power": 0
67
- },
68
- {
69
- "position": [
70
- 0,
71
- 28
72
- ],
73
- "steering": false,
74
- "max_angle_deg": 0,
75
- "power": 1.3,
76
- "brake_power": 1.5,
77
- "handbrake_power": 0
78
- },
79
- {
80
- "position": [
81
- 0,
82
- 22
83
- ],
84
- "steering": false,
85
- "max_angle_deg": 0,
86
- "power": 1.3,
87
- "brake_power": 1.5,
88
- "handbrake_power": 0
89
- },
90
- {
91
- "position": [
92
- 0,
93
- 16
94
- ],
95
- "steering": false,
96
- "max_angle_deg": 0,
97
- "power": 1.3,
98
- "brake_power": 1.5,
99
- "handbrake_power": 0
100
- }
101
- ]
102
- },
103
- "physics": {
104
- "real_precision": "single",
105
- "contact_recycle_radius": 1,
106
- "contact_max_separation": 1.5,
107
- "contact_max_allowed_penetration": 0.3,
108
- "contact_default_bias": 0.8,
109
- "solver_iterations": 16
110
- },
111
- "track": {
112
- "name": "Generated track template",
113
- "tiles": [],
114
- "path": [],
115
- "walls": [],
116
- "physics_shapes": []
117
- },
118
- "reset_position": [
119
- 0,
120
- 0
121
- ],
122
- "reset_rotation": 0
123
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
github-simulator/source/assets/scenes/truck_template.json DELETED
@@ -1,112 +0,0 @@
1
- {
2
- "vehicle": {
3
- "type": "Truck",
4
- "mass": 8,
5
- "inertia_property": 0,
6
- "inertia_server": 11059.5,
7
- "shape_size": [
8
- 124.5,
9
- 33
10
- ],
11
- "shape_position": [
12
- 0,
13
- 1.25
14
- ],
15
- "shape_rotation": 1.5708,
16
- "gravity_scale": 1,
17
- "linear_damp": 0,
18
- "angular_damp": 0,
19
- "max_contacts_reported": 4,
20
- "continuous_cd": "Disabled",
21
- "friction": 0.95,
22
- "bounce": 0.1,
23
- "grip": 12,
24
- "steering_speed": 0.15,
25
- "center_steering": true,
26
- "air_resistance": 0.4,
27
- "max_velocity": 600,
28
- "surfaces": {
29
- "asphalt": {
30
- "grip": 1,
31
- "power": 0.85,
32
- "steering": 1
33
- },
34
- "dirt": {
35
- "grip": 0.65,
36
- "power": 0.8,
37
- "steering": 1
38
- },
39
- "ice": {
40
- "grip": 0.15,
41
- "power": 0.7,
42
- "steering": 1
43
- }
44
- },
45
- "wheels": [
46
- {
47
- "position": [
48
- -17,
49
- -51
50
- ],
51
- "steering": true,
52
- "max_angle_deg": 22,
53
- "power": 0,
54
- "brake_power": 3.5,
55
- "handbrake_power": 0
56
- },
57
- {
58
- "position": [
59
- 17,
60
- -51
61
- ],
62
- "steering": true,
63
- "max_angle_deg": 22,
64
- "power": 0,
65
- "brake_power": 3.5,
66
- "handbrake_power": 0
67
- },
68
- {
69
- "position": [
70
- -17,
71
- 46
72
- ],
73
- "steering": false,
74
- "max_angle_deg": 0,
75
- "power": 6,
76
- "brake_power": 3,
77
- "handbrake_power": 3
78
- },
79
- {
80
- "position": [
81
- 17,
82
- 46
83
- ],
84
- "steering": false,
85
- "max_angle_deg": 0,
86
- "power": 6,
87
- "brake_power": 3,
88
- "handbrake_power": 3
89
- }
90
- ]
91
- },
92
- "physics": {
93
- "real_precision": "single",
94
- "contact_recycle_radius": 1,
95
- "contact_max_separation": 1.5,
96
- "contact_max_allowed_penetration": 0.3,
97
- "contact_default_bias": 0.8,
98
- "solver_iterations": 16
99
- },
100
- "track": {
101
- "name": "Generated track template",
102
- "tiles": [],
103
- "path": [],
104
- "walls": [],
105
- "physics_shapes": []
106
- },
107
- "reset_position": [
108
- 0,
109
- 0
110
- ],
111
- "reset_rotation": 0
112
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
github-simulator/source/docs/cli.md DELETED
@@ -1,115 +0,0 @@
1
- # CLI reference
2
-
3
- Run commands from the repository root or an unpacked release archive; both contain `assets/`. `altd-sim --version` identifies the build, including nightly packages. `--threads N` sets the Rayon pool; the default respects CPU affinity. `--mode independent|lockstep` selects native scheduling. Both are global flags. Each command's `--help` is the complete argument reference.
4
-
5
- `--math-profile proton|win10-fma3|win11-fma3` is also global and selects the game's C runtime arithmetic independently of the CPU or GPU backend. Every build includes all three profiles. Omitted profiles use `proton` on Linux/macOS, `win10-fma3` on Windows before build 26100, and `win11-fma3` on Windows build 26100 and newer. For example, `altd-sim --math-profile win11-fma3 train-scratch ...` trains for current Windows on any supported host. [Math profiles](../math/README.md) describes the version boundaries and implementation.
6
-
7
- ## Commands and inputs
8
-
9
- | Command | Required inputs and purpose |
10
- | --- | --- |
11
- | `bench` | `--scene`, `--network` with weights, `--spawn-trace`; fixed-population timing and optional state dumps |
12
- | `train` | `--scene`, weighted `--network`, `--model`, `--output`; evolution of an existing network |
13
- | `train-scratch` | `--scene`; Xavier initialization, checkpoints, generated batches and candidate export |
14
- | `evaluate` | `--network`, `--model`, `--suite`, `--report`; evaluate a frozen candidate without evolution |
15
- | `serve` | No input files; expose CPU or HIP sessions over a loopback WebSocket |
16
- | `compare-trace` | Positional scene, trace and report; replay controls from a recorded trace |
17
- | `compare-one-step` | Positional scene, trace and report; restore each recorded frame before stepping |
18
- | `compare-closed-loop` | Positional scene, trace, network, model and report; network-driven trajectory comparison |
19
- | `compare-network` | Positional network, trace and report; compare inference with recorded controls |
20
- | `compare-sensors` | Positional scene, trace, model, trajectory and report; compare sensor observations |
21
- | `compare-score` | Positional scene, trace and report; compare lap/score statistics |
22
- | `gpu-info` | Optional `--library`; load the GPU library used by `--gpu`, check its struct layouts and exports and, when a GPU is present, run one kernel on it |
23
-
24
- Scene and capture paths have no campaign defaults. `bench` and `train-scratch` default their sensor model to `assets/models/rally.json`. Scratch training defaults its sensor/control names to `assets/networks/rally.json`; these templates have no trained weights. The defaults are compiled into the binary, and `run.json` records them as `builtin:<path>`. Formula runs should explicitly use the Formula network/model assets and scene template.
25
-
26
- A fixed track requires `--spawn-trace` for `train` and `train-scratch`. The trace's first frame supplies the initial pose. Random mode needs only a geometry-free scene template; generated geometry supplies its reset pose. `--spawn-trace` is ignored in random mode. `bench` always requires its explicit spawn trace and supports `--spawn-index`.
27
-
28
- ```sh
29
- target/release/altd-sim --threads 8 bench \
30
- --scene wasm/test/scenarios/rally_mixed.scene.json \
31
- --spawn-trace wasm/test/scenarios/rally_mixed.spawn.json \
32
- --network wasm/test/scenarios/benchmark.network.json \
33
- --population 1024 --ticks 600
34
-
35
- cargo run --release --offline --example extract_saved_track -- \
36
- tests/fixtures/generated_saved_track.json example \
37
- assets/scenes/rally_template.json target/imported-scene.json
38
- ```
39
-
40
- The importer takes a saved-track export, a track name, a scene template and an output scene. Its bundled input is generated regression data. `tools/benchmark.py` runs the public generated-track bench repeatedly and keeps every report.
41
-
42
- ## Local server
43
-
44
- ```sh
45
- target/release/altd-sim --threads 8 serve --port 47800
46
- target/release/altd-sim serve --allow-origin http://127.0.0.1:5173
47
- ```
48
-
49
- `serve` binds `127.0.0.1` only and defaults to port 47800. Repeat `--allow-origin` to replace the default `https://drivinglab.jectrum.de` allowlist. The shared Rayon pool uses the global `--threads` flag. The server prints its address, allowed origins, thread count and HIP availability. It is included by the default `server` feature. See [the server protocol](server.md) for handshake checks, session operations, binary frames and resume behavior. Drive Lab client integration is a separate change.
50
-
51
- ## Scratch training
52
-
53
- Defaults are 8,192 cars, 50,000 target generations, a 5,400-tick time limit, seed 1, two inference batches and network shape `20,16,16,16,16,12,12,8,5`. The output directory defaults to `runs/example`. Pass short explicit limits for a smoke run. `--init-network` uses supplied weights; `--init-population` imports a compatible checkpoint into a new run directory.
54
-
55
- Evolution starts with tournament selection of 20 parents, no crossover, four preserved parents, adaptive mutation and no weight decay. Mutation decays geometrically from 0.4 to 0.0125; `--schedule linear` changes that schedule. `--settings FILE` overrides evolution defaults except requested population and scheduled mutation. It accepts a plain object or a nested `settings` object. Explicit elimination switches and `--reward` take precedence over the file.
56
-
57
- Elimination defaults off. `--eliminate-on-wall` deactivates cars after native wall contact. `--idle-eliminate` deactivates cars after more than 80 consecutive statistics updates with insufficient forward progress. The corresponding `--no-*` switches disable them. Passive physics and pending contacts continue for inactive cars.
58
-
59
- `--reward distance` selects on `total_score`; `--reward best-lap-time` selects on reciprocal best completed lap time. Without an explicit reward, settings-file rewards remain, with distance as the fallback. Cars without a completed lap have no best-lap signal.
60
-
61
- ## Generated track batches
62
-
63
- ```sh
64
- target/release/altd-sim --threads 8 train-scratch \
65
- --scene assets/scenes/rally_template.json --track-mode random \
66
- --random-track-settings assets/random_track_settings.json \
67
- --tracks-per-generation 3 --track-buffer-size 8 \
68
- --population 256 --generations 3 --ticks 600 --seed 1729 \
69
- --save-final-candidate --out-dir runs/example
70
- ```
71
-
72
- Each unchanged population evaluates the same track batch, with fresh spawn and a separate tick limit on each track. Selection uses the mean of normalized per-track reward ranks. Reproduction and the mutation schedule advance once after the complete batch. Fixed mode allows one track only. Queue depth changes preparation capacity, not the RNG stream.
73
-
74
- Without a settings file, track lengths range from 12 to 40 even tiles, all block types are enabled, and one, two or three distinct surfaces are sampled with equal probability into consecutive sections. `assets/random_track_settings.json` is an explicit variant that also samples double-block choices and random/section surface distribution.
75
-
76
- | Track field | Values |
77
- | --- | --- |
78
- | `length` | Fixed even count, or inclusive `{"min": 12, "max": 40}` range; supported grid capacity 4 to 76 |
79
- | `allow_double` | Boolean or list of boolean choices |
80
- | `surfaces` | Fixed distinct IDs, list of sets, or `{"pool": [0,1,2], "count": [1,2,3]}` |
81
- | `distribution` | `0` random per tile, `1` consecutive sections, or choices |
82
- | `start` | `null` for a fresh position, or fixed grid `[x,y]` |
83
-
84
- Surface IDs are asphalt 0, dirt 1 and ice 2. Failed generation retries are bounded; invalid or impossible settings fail rather than silently changing a fixed requested length. Track seeds depend on run seed, generation and batch slot independently of reproduction RNG, worker count and backend.
85
-
86
- ## Outputs, resume and stopping
87
-
88
- `run.json` stores effective options from the latest invocation. `log.jsonl` has one completed-generation row, with per-track statistics for random batches. `progress.json` publishes current batch progress atomically. Generated track exports live under `tracks/`. `best.json` and `best_laps/` retain the fastest individual lap, even when selection uses another reward.
89
-
90
- Checkpoints are saved every `--checkpoint-every` generations, default 100, and after normal termination. Zero disables them. `checkpoint.json` identifies a binary population file and stores shape, population, generation and RNG state. `--resume` restores the latest complete generation boundary and removes replayed log/geometry entries. It cannot preserve every mid-tick native contact cache.
91
-
92
- ```sh
93
- target/release/altd-sim train-scratch --resume \
94
- --scene assets/scenes/rally_template.json --track-mode random \
95
- --random-track-settings assets/random_track_settings.json \
96
- --population 256 --generations 6 --ticks 600 --out-dir runs/example
97
- ```
98
-
99
- `--generations` is the total target, including saved generations. Supply desired options again: omitted options use CLI defaults, except track seed/count retained in checkpoint metadata. An explicit `--tracks-per-generation` replaces the saved count. Preserve scene and track settings to reproduce the original sequence. Saved networks/RNG take precedence over a new `--seed` or `--init-network` during resume.
100
-
101
- `train-scratch --resume` also retains the checkpoint's math profile; an explicit different `--math-profile` is rejected. Checkpoints predating profiles use `proton`. New `run.json` and checkpoint metadata record `math_profile` so moving a run to another host does not change its arithmetic.
102
-
103
- Shape must match every checkpoint layer; matching parameter counts alone is insufficient. Population reductions keep the first networks, while expansions repeat them in order. Mutation uses the newly supplied schedule at the restored generation. Earlier checkpoints without shape/population recover those fields from adjacent `run.json` before updating current options.
104
-
105
- `--save-final-candidate` writes the complete-batch fitness leader before breeding, with lowest-index tie breaking. It preserves exact weights, ordered names, generation and reward metadata without consuming RNG. A completed checkpoint confirms its filename/hash/generation. A candidate without that confirmation is not a completed-stage result.
106
-
107
- `--stop-score-above`, `--stop-lap-below`, `--stop-lapped-percent` and `--stop-plateau` stop after a qualifying complete batch. Lap targets require a car to lap every track. Plateau counters restart per invocation, using `--plateau-metric lap|score`. A `stop_request` file in the run directory stops after the current batch; a stale file is removed at startup. SIGTERM does not write a final checkpoint. Negative thresholds use `=`, for example `--stop-score-above=-100`.
108
-
109
- ## Frozen evaluation
110
-
111
- `evaluate` reads a version-1 suite containing `vehicle`, `options` and distinct `tracks`. Every track specifies relative scene/spawn filenames, their SHA-256 hashes and a finite tick limit. Options specify CPU backend, inference batch count and elimination. The evaluator validates finite network parameters, shape, ordered sensor/control names, vehicle compatibility and input hashes.
112
-
113
- A suite may set `options.math_profile` to a supported profile. An explicit CLI profile must agree with it. Without either, evaluation detects the host's profile; the report records the effective `math_profile`.
114
-
115
- Each track gets fresh state, contacts, controls, sensors and statistics. The evaluator never breeds or modifies training checkpoints/logs. Its atomic report records candidate/suite/simulator hashes, per-track score, progress, lap completion, optional best lap, collisions and executed ticks. An interrupted run does not publish a successful report. Existing tests build fully contained suites from fixed generated tracks.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
github-simulator/source/docs/design.md DELETED
@@ -1,59 +0,0 @@
1
- # Design notes
2
-
3
- The simulator keeps arithmetic and execution ordering visible. A small algebraic rewrite can change rounding, contact choices or evolution, so numeric code and scheduling need stronger regression evidence than ordinary I/O changes.
4
-
5
- ## Modules and ownership
6
-
7
- | Directory | Modules | Responsibility |
8
- | --- | --- | --- |
9
- | `src/math/` | `godot_math`, `native_math`, `managed_trig`, `double_math`, `pymath`, `vec2` | Captured rounding, runtime arithmetic and vectors |
10
- | `src/physics/` | `car`, `collision`, `simulation`, `broadphase`, `trace_state` | Forces, passive bodies, contacts, population physics and recorded-state reconstruction |
11
- | `src/track/` | `world`, `curve`, `bsp`, `segment_grid`, `path_segments`, `random_track`, `training_tracks` | Scene loading, geometry queries, tile generation and bounded preparation queue |
12
- | `src/nn/` | `network`, `network_simd` | Flat parameters and scalar/AVX2 inference |
13
- | `src/training/` | `agent`, `lineage`, `sensors`, `stats`, `runner`, `evolution`, `batch_evaluation`, `game_random`, `pyrandom` | Populations, statistics, ordered execution, reproduction and RNG backends |
14
- | `src/training/` | `session`, `evaluation` | Embedding, generation checkpoints and evaluation reports |
15
- | `src/gpu/` | `hip`, `simulation` | Runtime-loaded HIP C API, shared layouts and GPU windows |
16
- | `src/wasm/` | `gpu`, `sim` | JavaScript bindings, WebGPU rays and full simulation |
17
-
18
- Library imports follow the directory groups. For example, `physics::car::Car` and `track::world::World` describe their roles directly. The training scheduler types remain available from `training`, and embedding sessions live in `training::session`. HIP loading uses `gpu::hip`; portable GPU layouts live in `gpu::simulation`.
19
-
20
- The CLI entrypoint is `src/bin/altd-sim/main.rs`. Its sibling modules use Cargo's standard binary layout: `args` defines the command contract, `comparisons` produces recorded-trace reports, `bench` and `train` run their workloads, and `scratch` owns run configuration, stopping rules, checkpoint I/O and execution. Scratch parameter checkpoints and Session lineage checkpoints remain separate formats.
21
-
22
- The GPU validation example uses private modules in `examples/gpu_check/` for math, rays, simulation, evolution and benchmarks. Shared fixture setup and mismatch reporting stay outside the checked numerical implementations.
23
-
24
- CPU runners own populations and checkpoint serialization. HIP retains uploaded networks and geometry between windows; CPU evolution installs offspring and preserves the CPU/GPU resume format. WebGPU full simulation mirrors state in browser buffers and commits complete windows back to the Session. A failed window leaves the last committed state available for CPU continuation.
25
-
26
- ## Execution modes
27
-
28
- Independent mode advances each car through a window, keeping its state and network near the CPU. Lockstep advances the population one tick at a time. Scenes requesting native shared broadphase require tick-major execution to preserve population contact ordering. Generated CLI training disables that shared broadphase so CPU and GPU use independent car physics.
29
-
30
- Statistics run before driving. Inference uses eight original index-based batches, so compacting inactive work must preserve each car's batch identity. Eliminated cars stop driving and scoring, but passive physics and pending contact accounting continue. The generation limit is checked on the statistics callback, so actual callback counts can slightly exceed a requested tick cap.
31
-
32
- Raycaster windows keep physics and inference on the CPU and replace only ray queries. HIP and full WebGPU windows run those phases on-device. These paths have distinct scheduling and memory costs; shared arithmetic names do not make their loop structure interchangeable.
33
-
34
- ## Reproducible tracks and checkpoints
35
-
36
- Track seeds depend on the run seed, generation and batch slot. Their RNG stream is separate from network reproduction. Bounded queue depth and worker timing therefore do not affect which tracks a generation receives. Each batch shares a track across its population and breeds once after all tracks.
37
-
38
- Scratch CLI checkpoints save the next generation's population and RNG state at generation boundaries. Session checkpoints can encode parent lineage instead of every child network while retaining exact reconstruction. Those formats have different consumers and should be treated as separate contracts. Neither promises to serialize every mid-tick native contact cache.
39
-
40
- ## Numerical constraints
41
-
42
- Keep float32/float64 transitions, reduction order, runtime transcendental behavior and equal-distance query decisions explicit. Disable FMA contraction in HIP builds. Preserve cached Gaussian draws and both captured game RNG streams. Generate shared numeric tables from their bit patterns and check the generated header before building; GPU builds must not rewrite source files.
43
-
44
- Performance changes need workload medians as well as exact state, checkpoint and RNG comparisons. Profiling paths alter launch behavior, so final timing should use production settings. [Fidelity](fidelity.md) and [performance](performance.md) describe the evidence and its boundaries.
45
-
46
- ## Formatting and lint checks
47
-
48
- `cargo fmt --all -- --check` uses the repository's 120-column width. Native checks use `cargo clippy --offline --all-targets -- -D warnings`. Browser bindings use `cargo clippy --offline --target wasm32-unknown-unknown --no-default-features --features wasm -- -D warnings`. Scoped lint allowances explain preserved runtime constants, nonfinite comparisons, indexed numerical loops and packed GPU layouts. They do not relax warnings for unrelated code.
49
-
50
- ## Optimizers
51
-
52
- `TrainingRunner` evaluates a whole population, scores it with `reward_values` (ranks within the generation), and hands the cars and scores to an `Optimizer` (`src/training/optimizer.rs`), which returns the next population. `settings.algorithm` chooses one; the runner replaces its optimizer when the name changes, and the new one continues from the cars it is next given.
53
-
54
- - `"ga"` is the default: selection, crossover, mutation and decay as in `evolution.rs`. Its random draws, and so every GA checkpoint and test, are unchanged.
55
- - `"ars"` (`src/training/ars.rs`) is Augmented Random Search V2-t with an elite pool. It keeps a search point `theta`; the population is the elites, `theta`, and antithetic probes `theta ± nu·d`, and the scores steer one step `alpha/(b·nu)·Σ(r+ − r−)·d` over the best `top_frac` of the pairs. The step is skipped when the scores are all alike. Elites are the best distinct cars of the last population, old elites included; they are re-run unchanged every generation, so ranks from different generations are never compared. Settings live under `settings.ars` (`nu`, `alpha`, `top_frac`, `elite_count`, `max_weight`), and `population` must be at least `elite_count + 3`.
56
-
57
- Rewards stay rank based for every algorithm. ARS therefore behaves like rank-based OpenAI-ES with top-b pair selection rather than reference ARS on raw magnitudes.
58
-
59
- Session checkpoints record how a population was made, so each optimizer has its own format: `ALTDCKP2` for GA parent lineage and `ALTDCKP3` for ARS, which stores `theta`, the elite pool, the sampling settings and the generator before the directions were drawn. Restoring one resamples the population and the directions exactly. A full population checkpoint (`ALTDCKP1`, JSON checkpoints, scratch CLI checkpoints) carries no search state, so ARS continues from the best restored car. A changed population size does the same.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
github-simulator/source/docs/fidelity.md DELETED
@@ -1,37 +0,0 @@
1
- # Fidelity and regression coverage
2
-
3
- The simulator targets the captured behavior of AI Learns To Drive. Physics mixes float32 state with float64 calculations, and callbacks, contact caches and inference batches have observable ordering. Matching formulas alone does not reproduce those results.
4
-
5
- Numerical implementations retain operation order, intermediate precision, rounding boundaries, tie-breaking and RNG consumption. Scalar and AVX2 inference accumulate in the same order. HIP builds disable multiply-add contraction and require correctly rounded float32 division and square root. Spatial acceleration preserves traversal and first-equal-result decisions. A change to any of these rules needs exact comparisons before performance measurements.
6
-
7
- ## What the tests establish
8
-
9
- The game captures in `tests/fixtures/` exercise native vehicle transitions, population lifecycle, contact/reset behavior, runtime math, sensors, statistics and training. Their track geometry comes from synthetic cases or generated tracks. Campaign tracks are not distributed. Short recorded vehicle-state samples retain positions, contact points and scalar sensor outputs, with collider exports removed. They are finite oracle samples. Older traces sometimes omit body matrices or contact caches, so restoring their visible state cannot prove complete native state reconstruction.
10
-
11
- Packed-game captures use Godot 4.3 build 77dcf97d8 and Windows .NET 8.0.2 where the fixture records that setup. The capture harnesses and raw logs are not distributed. Fixture provenance names the runtime and harness without presenting unavailable paths as public tooling. Packed-sine lookup tables were extracted from Windows .NET 8.0.2 coreclr.dll; their source hash remains in the table header, and the extraction script is not distributed.
12
-
13
- Generated-track game captures cover parked TileMaps, native wall insertion order, single-vehicle and population contacts, live resizing, redraws, coalesced creation, Truck and Snowmobile behavior, terrain grip and ordered/path sensors. Their `recipe` fields select a fixed generator seed, generation and slot using the public settings and vehicle template. Tests rebuild the geometry and apply explicit scene overrides; output states, curve samples and sensor values come from the game. These captures are separate from simulator-generated goldens.
14
-
15
- Generated-track goldens record the simulator's current results for controlled contacts, restored states, scoring, population redraw and Session checkpoints. They detect regressions; they are not independent game captures. Fixtures and their origins are documented in [the fixture README](../tests/fixtures/README.md). Differential tests compare accelerated queries with brute force, and CLI tests cover settings, checkpoints, resume, generated batches and evaluation.
16
-
17
- A historical diagnostic comparison against a captured campaign run matched 1,393 of 1,398 one-step frames exactly. The remaining five differed in angular velocity, rotation or velocity. Network inference matched all 1,398 frames with zero error. These results predate the public generated-track replacements and describe that capture, not every scene or closed-loop run. The campaign run and its geometry are not public inputs.
18
-
19
- ## Platform limits
20
-
21
- On x86, native `engine_sin_cos` uses x87 `FSINCOS`. Its large-argument reduction preserves the extended pi constant across x87 precision modes. Tests cover 24, 53 and 64-bit precision and check that the caller's control word is unchanged. The portable fdlibm-based implementation is validated against x87 over float32 arguments with absolute value at most 16; the regular suite samples the domain and an ignored exhaustive test scans it. Larger arguments are not covered by that claim.
22
-
23
- Nonfinite float32 trig outputs retain the captured NaN signs and payloads on every target. Scalar and engine routines quiet NaNs. Managed `SinCos` preserves the sine input bits and clears the sign while quieting cosine. Both infinities produce the captured x86 indefinite NaN, `0xffc00000`.
24
-
25
- The distance-from-wall sensor also returns the x86 indefinite for zero divided by zero and infinity divided by infinity, including float32 conversion boundaries. Quotients from NaN operands retain their payloads.
26
-
27
- Seeded Python Xavier tests keep the captured parameter checksum on Linux and Windows. On macOS, `cargo test --lib nn::network::tests::xavier_matches_python -- --exact` requires `python3` and compares every parameter bit, the MT state and the cached Gaussian draw with CPython on that host. This checks host parity without assuming libSystem and glibc round identically.
28
-
29
- Seeded initialization uses host float64 transcendental functions. Equal RNG draws can therefore produce different parameter bits across native hosts. Session regressions compare both execution modes with the legacy `TrainingRunner` on each host and require exact checkpoint replay. Stored Session snapshot and checkpoint goldens remain exact comparisons on their capture platform, Linux x86_64 GNU.
30
-
31
- Native and WASM use different host implementations for some float64 transcendental operations. The public generated Formula state scenario matched 2,773 native values, while expanded snapshots found 2,285 native differences per scheduling mode: 703 controls, 405 metrics and 1,177 checkpoint bytes. Serial and threaded WASM had the same native differences and matched each other in all 253,341 checked values per mode, including the optional score aggregates. A passing state-only comparison does not imply exact expanded native parity. Counts depend on the scenario and checkpoint layout.
32
-
33
- The RX 7900 XTX WebGPU raycaster matched 4,000 random rays, 4,000 nearest-wall points and 119,743 in-simulation rays in that baseline. WGSL floating-point behavior, subnormal handling and NaN payloads still vary by device. Runtime verification counts discrepancies without replacing GPU results. See [WASM notes](wasm.md) for the comparison layers.
34
-
35
- ## Checking a change
36
-
37
- Run native tests in debug and release, regenerate observations to temporary outputs, and compare exact float bits, RNG state and checkpoint bytes. Exclude only named timing and path metadata when comparing reports. Keep generated references separate from captured oracle data. Measure throughput only after those checks pass.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
github-simulator/source/docs/gpu.md DELETED
@@ -1,31 +0,0 @@
1
- # HIP implementation notes
2
-
3
- The HIP library runs statistics, sensing, network inference and vehicle physics for independent cars. It also supports GPU turnover through the runner API. Population mean and novelty run on the GPU with reductions in the original order; that turnover path keeps offspring weights uploaded for the next generation. Rust owns resets and checkpoints.
4
-
5
- The same sources build for NVIDIA GPUs with `nvcc` (`gpu/build-cuda.*`, `gpu/sim/compat.h`); this page applies to both. NVIDIA warps are 32 lanes and use the `*_sync` warp operations with a full mask, so every lane of a wave must reach `reserve`, `append` and the active-count ballot, as on AMD. NVIDIA arithmetic returns its canonical NaN where the CPU returns a NaN operand, so those results are built explicitly on both vendors (`altd_nan_operand`, `altd_invalid`).
6
-
7
- ## HIP sessions
8
-
9
- Native `SessionOptions` accepts `backend: "hip"` as well as the default `"cpu"`. The same option is available to [local server](server.md) clients. WASM sessions reject HIP. The process opens the HIP library once and allows one HIP session at a time; a session that cannot use HIP reports CPU through `backend()` and a reason through `backend_note()`.
10
-
11
- HIP sessions drive through the existing GPU window and generation paths, then read car and agent state back into the CPU runner. Readers, metrics and checkpoints therefore use the same runner state as CPU sessions. The simulator grows when a restored or started population exceeds its capacity, and track replacement uploads a new GPU world.
12
-
13
- Before the first window after a start or restore, a session compares 12 CPU and HIP ticks exactly from a backed-up state. It restores that state before real driving. Track replacement also requires a new comparison. A mismatch or verification error switches the session to CPU; a later HIP window error returns an error without retrying.
14
-
15
- Session turnover uses CPU `next_generation_traced`, which retains the parent records needed by format-2 checkpoints. The next HIP window uploads the new networks. Start, restore and network replacement also invalidate the uploaded network cache. This differs from the runner's GPU turnover path, which does not produce those parent records.
16
-
17
- Native CPU and HIP sessions share checkpoint formats with WASM. Native and WASM results have known last-bit differences; switching engines preserves the checkpoint but may change later training.
18
-
19
- ## Kernels and validation
20
-
21
- Kernels compact live work into eight original inference batches. Only due batches run sensing and inference. A separate physics list retains inactive cars until they settle exactly. Windows replay a HIP graph over the 24-tick statistics/inference period, with direct launches for remainders. Compatible windows reuse the graph; changing track, schedule, shape, population or output mapping invalidates it.
22
-
23
- The split physics path separates collision phases and preserves ordered per-car contact generation. `ALTD_GPU_SPLIT=0` selects the fused alternative. `ALTD_GPU_GRAPH=0` bypasses graphs. These are differential validation options, not promises of better performance.
24
-
25
- The network forward path uses double parameters and adds products in input order. This can dominate at large populations on GPUs with low double-precision throughput. Host buffers retain mutation noise and upload packing space. A 262,144-car population with 1,661 parameters requires about 3.24 GiB for that host double buffer alone; device memory, car state and checkpoint populations are additional.
26
-
27
- `gpu::simulation` mirrors C layouts explicitly and exports/imports canonical car and agent state. The loader resolves the shared library at runtime, so ordinary CPU builds do not link ROCm. Rebuild the Rust executable and library together when their C API or layouts change.
28
-
29
- Historical CPU/HIP checks cover primitive math, queries, sensors, inference, physics, turnover, batch wrapping, uneven populations, simulator reuse and resumed training. They compare flags, exact values, RNG state and population bytes. These finite checks do not establish exactness for every scene or device. Run the generated-input checks on your own GPU using [the GPU guide](../gpu/README.md). [Performance notes](performance.md) retain measured results and timing boundaries.
30
-
31
- On Linux, `python3 gpu/test_constructor_cleanup.py` checks the built library's constructor failure paths without allocating GPU memory. It requires a C++17 compiler and the ROCm runtime. A temporary HIP shim injects allocation and copy failures, then checks that device buffers, host buffers, events and streams are released. The ROCm CI job runs this check without a GPU.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
github-simulator/source/docs/math-profiles.html DELETED
@@ -1,415 +0,0 @@
1
- <!doctype html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="utf-8">
5
- <title>Math profiles: supporting Windows UCRT variants on every backend</title>
6
- <style>
7
- :root {
8
- --bg: #0f1216; --panel: #171b21; --ink: #e6e9ee; --mute: #98a2b3; --line: #2a313b;
9
- --musl: #3b82f6; --ucrt: #f59e0b; --ucrt2: #ef4444; --ok: #22c55e; --gen: #a855f7; --hand: #f97316;
10
- }
11
- * { box-sizing: border-box; }
12
- body { margin: 0; background: var(--bg); color: var(--ink); font: 15px/1.5 system-ui, -apple-system, "Segoe UI", sans-serif; }
13
- main { max-width: 1240px; margin: 0 auto; padding: 32px 28px 64px; }
14
- h1 { font-size: 28px; margin: 0 0 6px; }
15
- h2 { font-size: 21px; margin: 44px 0 12px; padding-bottom: 6px; border-bottom: 1px solid var(--line); }
16
- h3 { font-size: 16px; margin: 22px 0 8px; }
17
- p, li { color: #cfd5de; }
18
- .sub { color: var(--mute); margin: 0 0 22px; }
19
- code { font: 13px ui-monospace, "SF Mono", Menlo, Consolas, monospace; background: #1f252d; padding: 1px 5px; border-radius: 4px; color: #e2e8f0; }
20
- .tldr { background: var(--panel); border: 1px solid var(--line); border-left: 4px solid var(--ok); border-radius: 8px; padding: 14px 18px; }
21
- .tldr ul { margin: 6px 0 0; padding-left: 20px; }
22
- table { border-collapse: collapse; width: 100%; margin: 10px 0; font-size: 14px; }
23
- th, td { border: 1px solid var(--line); padding: 7px 9px; text-align: left; vertical-align: top; }
24
- th { background: #1b2027; color: #dbe1ea; font-weight: 600; }
25
- td { background: var(--panel); }
26
- .matrix td { text-align: center; font: 13px ui-monospace, Menlo, monospace; }
27
- .matrix td:first-child, .matrix th:first-child { text-align: left; font-family: system-ui, sans-serif; }
28
- .v0 { background: #14243f !important; color: #93c5fd; }
29
- .v1 { background: #3a2a0c !important; color: #fcd34d; }
30
- .v2 { background: #3f1a12 !important; color: #fdba74; }
31
- .v3 { background: #3b1220 !important; color: #fda4af; }
32
- .v4 { background: #2a1840 !important; color: #d8b4fe; }
33
- .na { color: #5b6574 !important; }
34
- .grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
35
- .card { background: var(--panel); border: 1px solid var(--line); border-radius: 8px; padding: 14px 16px; }
36
- .card h3 { margin-top: 0; }
37
- .figure { background: var(--panel); border: 1px solid var(--line); border-radius: 10px; padding: 10px; margin: 10px 0 6px; overflow-x: auto; }
38
- .caption { color: var(--mute); font-size: 13px; margin: 4px 2px 0; }
39
- .legend { display: flex; gap: 16px; flex-wrap: wrap; font-size: 13px; color: var(--mute); margin: 6px 2px; }
40
- .sw { display: inline-block; width: 12px; height: 12px; border-radius: 3px; vertical-align: -1px; margin-right: 5px; }
41
- .bad { color: #fca5a5; } .good { color: #86efac; }
42
- .tag { display: inline-block; font-size: 11px; padding: 1px 7px; border-radius: 10px; border: 1px solid var(--line); color: var(--mute); margin-left: 6px; }
43
- ol.phases > li { margin-bottom: 10px; }
44
- svg text { font-family: system-ui, -apple-system, "Segoe UI", sans-serif; }
45
- </style>
46
- </head>
47
- <body>
48
- <main>
49
-
50
- <h1>Math profiles</h1>
51
- <p class="sub">Historical design draft for issue #7, based on code at <code>e96a2e8</code> and the 56-build UCRT survey. The original proposal and diagrams below are retained as design history.</p>
52
-
53
- <div class="tldr">
54
- <strong>Implemented profiles</strong>
55
- <p>The implementation supports <code>proton</code>, <code>win10-fma3</code> and <code>win11-fma3</code>. Every native/WASM/GPU build includes all three. Defaults detect the host's operating system and version; resumed runs retain their saved profile. SSE2 variants are outside the supported scope.</p>
56
- <p>The new Windows kernels share restricted C source in <code>math/kernels/ucrt.h</code>, translated to Rust/WASM and WGSL and included by HIP/CUDA. The established musl and AVX2 ports remain. WebGPU pipeline creation specializes the generated module for the session's profile. <a href="../math/README.md">Current kernel, fixture and verification documentation</a> describes the implemented architecture.</p>
57
- </div>
58
-
59
- <h2>Original proposal</h2>
60
-
61
- <div class="tldr">
62
- <strong>TL;DR</strong>
63
- <ul>
64
- <li>Make the platform's C runtime a <b>runtime parameter</b> (<code>MathProfile</code>) instead of a fact baked into every backend. Five profiles cover everything we measured: Proton and four Windows ones.</li>
65
- <li>Write each math variant <b>once</b>, in the restricted C subset that <code>gpu/sim/*.h</code> already uses, and <b>generate</b> the Rust, AVX2, HIP and WGSL versions from it. This extends the existing <code>gen-sim.py</code> / <code>gen_tables.py</code> pipeline instead of adding a new one.</li>
66
- <li>Use <b>exception tables</b> where exhaustive proof is possible (<code>sinf</code>/<code>cosf</code>: every float32 can be checked, as <code>engine_exceptions.h</code> already does for x87). Use <b>algorithm ports</b> for the rest (<code>atan2f</code>, <code>exp</code>, <code>log</code>, <code>pow</code>, <code>tanh</code>).</li>
67
- <li>Verify each (profile × backend) pair against golden vectors captured from genuine DLLs under Wine. Only the output bits are stored; the DLLs are not.</li>
68
- <li>The default stays <code>proton</code>, so existing goldens, checkpoints and behaviour don't change until a user chooses another profile.</li>
69
- </ul>
70
- </div>
71
-
72
- <h2>1. What has to be supported (measured)</h2>
73
- <p>Results of the 56-build survey: genuine x64 <code>ucrtbase.dll</code> builds signed 2020–2026, each tested with FMA3 on and off. Each cell shows which implementation a profile needs. A different colour means a different implementation, i.e. not bit-identical.</p>
74
-
75
- <table class="matrix">
76
- <tr><th>Function (who uses it)</th><th>proton</th><th>win10-fma3<br><span class="tag">Win10, Win11 ≤23H2</span></th><th>win10-sse2</th><th>win11-fma3<br><span class="tag">Win11 24H2+</span></th><th>win11-sse2</th><th>impls</th></tr>
77
- <tr><td><code>sinf</code> (ray directions, vision)</td><td class="v0">musl</td><td class="v1">ucrt·F</td><td class="v2">ucrt·S</td><td class="v1">ucrt·F</td><td class="v2">ucrt·S</td><td>3</td></tr>
78
- <tr><td><code>cosf</code> (ray directions, vision)</td><td class="v0">musl</td><td class="v1">ucrt·F</td><td class="v2">ucrt·S</td><td class="v1">ucrt·F</td><td class="v2">ucrt·S</td><td>3</td></tr>
79
- <tr><td><code>atan2f</code> (rotation, sensors, slip, tracks)</td><td class="v0">musl</td><td class="v1">ucrt</td><td class="v1">ucrt</td><td class="v1">ucrt</td><td class="v1">ucrt</td><td>2</td></tr>
80
- <tr><td><code>exp</code> (tyre grip)</td><td class="v0">musl</td><td class="v1">A·F</td><td class="v2">S</td><td class="v3">B·F</td><td class="v2">S</td><td>4</td></tr>
81
- <tr><td><code>log</code> (Box-Muller, evolution; CPU only)</td><td class="v0">musl</td><td class="v1">ucrt</td><td class="v1">ucrt</td><td class="v1">ucrt</td><td class="v1">ucrt</td><td>2</td></tr>
82
- <tr><td><code>pow</code> (input easing, novelty)</td><td class="v0">musl</td><td class="v1">A·F</td><td class="v2">A·S</td><td class="v3">B·F</td><td class="v4">B·S<sup>†</sup></td><td>5</td></tr>
83
- <tr><td><code>tanh</code> (network activation)</td><td class="v0">musl</td><td class="v1">A</td><td class="v1">A</td><td class="v3">B·F</td><td class="v1">A</td><td>3</td></tr>
84
- <tr><th>Total implementations</th><th colspan="5" style="text-align:left">today: 7 (one per function) · needed: <b>22</b></th><th>22</th></tr>
85
- </table>
86
- <p class="caption">A = Windows 10 / Win11 ≤23H2 behaviour, B = Win11 24H2+ behaviour, F = FMA3 path, S = SSE2 path. Profile-independent and unchanged: x87 <code>engine_sin_cos</code>, .NET <code>MathF.SinCos</code> (<code>managed_sin_cos</code>). <sup>†</sup>B·F and B·S <code>pow</code> agree on all game-range inputs and differ on 10 of 4M wide inputs.</p>
87
-
88
- <div class="grid2">
89
- <div class="card">
90
- <h3>Where each function runs today</h3>
91
- <table>
92
- <tr><th></th><th>CPU scalar</th><th>AVX2</th><th>HIP</th><th>WebGPU</th></tr>
93
- <tr><td>sinf / cosf</td><td>✓</td><td class="na">–</td><td>✓</td><td>✓</td></tr>
94
- <tr><td>atan2f</td><td>✓</td><td class="na">–</td><td>✓</td><td>✓</td></tr>
95
- <tr><td>exp, pow</td><td>✓</td><td class="na">–</td><td>✓</td><td>✓</td></tr>
96
- <tr><td>log</td><td>✓</td><td class="na">–</td><td class="na">–</td><td class="na">–</td></tr>
97
- <tr><td>tanh</td><td>✓</td><td>✓ <code>tanh4</code></td><td>✓</td><td>✓</td></tr>
98
- </table>
99
- <p class="caption">WASM CPU compiles the same Rust as native scalar. <code>log</code> only runs in reproduction, which stays on the CPU in HIP and WebGPU sessions.</p>
100
- </div>
101
- <div class="card">
102
- <h3>Why a naive port doesn't scale</h3>
103
- <p>Hand-porting 22 implementations to every backend would mean 22 Rust + 20 HIP + 3 AVX2 bit-exact ports, each needing review, plus 22 generated WGSL functions to validate. Today 7 Rust + 6 HIP + 1 AVX2 are maintained by hand.</p>
104
- <p>The FMA3 variants also need <b>explicit fused multiply-adds</b>. HIP builds deliberately use <code>-ffp-contract=off</code>, and WGSL has no <code>f64</code> at all (<code>f64.wgsl</code> is software binary64). So "just enable FMA" isn't an option anywhere.</p>
105
- </div>
106
- </div>
107
-
108
- <h2>2. Current state</h2>
109
- <div class="figure">
110
- <svg viewBox="0 0 1200 470" width="100%" role="img" aria-label="Current architecture">
111
- <defs>
112
- <marker id="ah" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#98a2b3"/></marker>
113
- <marker id="ahh" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#f97316"/></marker>
114
- <marker id="ahg" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#a855f7"/></marker>
115
- </defs>
116
- <!-- column labels -->
117
- <text x="20" y="28" fill="#98a2b3" font-size="13">SPECIFICATION (one fixed platform: Proton / musl)</text>
118
- <text x="470" y="28" fill="#98a2b3" font-size="13">BACKEND IMPLEMENTATIONS</text>
119
- <text x="900" y="28" fill="#98a2b3" font-size="13">CALLERS (hard-wired)</text>
120
-
121
- <!-- Rust spec -->
122
- <rect x="20" y="45" width="370" height="170" rx="8" fill="#14243f" stroke="#3b82f6"/>
123
- <text x="36" y="70" fill="#e6e9ee" font-size="15" font-weight="600">Rust scalar = the reference</text>
124
- <text x="36" y="94" fill="#cfd5de" font-size="13">src/math/native_math.rs — sinf, cosf, atan2f</text>
125
- <text x="36" y="114" fill="#cfd5de" font-size="13">src/math/double_math.rs — exp, log, pow</text>
126
- <text x="36" y="134" fill="#cfd5de" font-size="13">src/nn/network.rs — game_tanh / game_expm1</text>
127
- <text x="36" y="154" fill="#cfd5de" font-size="13">src/math/double_math_tables.rs</text>
128
- <text x="36" y="182" fill="#93c5fd" font-size="12.5">Free functions; no notion of "which platform".</text>
129
- <text x="36" y="200" fill="#93c5fd" font-size="12.5">Also compiled for WASM CPU.</text>
130
-
131
- <!-- AVX2 -->
132
- <rect x="470" y="45" width="360" height="62" rx="8" fill="#2a1d10" stroke="#f97316"/>
133
- <text x="486" y="70" fill="#e6e9ee" font-size="14" font-weight="600">AVX2 src/nn/network_simd.rs</text>
134
- <text x="486" y="92" fill="#fdba74" font-size="12.5">tanh4 / expm1_tanh — hand port of game_tanh</text>
135
-
136
- <!-- HIP -->
137
- <rect x="470" y="127" width="360" height="88" rx="8" fill="#2a1d10" stroke="#f97316"/>
138
- <text x="486" y="152" fill="#e6e9ee" font-size="14" font-weight="600">HIP gpu/sim/math.h</text>
139
- <text x="486" y="174" fill="#fdba74" font-size="12.5">native_sin/cos/atan2, dexp, dpow, game_tanh</text>
140
- <text x="486" y="194" fill="#fdba74" font-size="12.5">hand port; -ffp-contract=off</text>
141
-
142
- <!-- tables gen -->
143
- <rect x="470" y="235" width="360" height="50" rx="8" fill="#1f1530" stroke="#a855f7"/>
144
- <text x="486" y="258" fill="#e6e9ee" font-size="14" font-weight="600">gpu/gen_tables.py → double_tables.h</text>
145
- <text x="486" y="276" fill="#d8b4fe" font-size="12.5">bit-copied from Rust tables</text>
146
-
147
- <!-- WGSL -->
148
- <rect x="470" y="305" width="360" height="88" rx="8" fill="#1f1530" stroke="#a855f7"/>
149
- <text x="486" y="330" fill="#e6e9ee" font-size="14" font-weight="600">WebGPU src/wasm/sim/generated.wgsl</text>
150
- <text x="486" y="352" fill="#d8b4fe" font-size="12.5">wasm/gen-sim.py transpiles gpu/sim/*.h (pycparser)</text>
151
- <text x="486" y="372" fill="#d8b4fe" font-size="12.5">doubles via f64.wgsl (software binary64)</text>
152
-
153
- <!-- arrows spec -> backends -->
154
- <path d="M390,90 C430,90 430,76 466,76" stroke="#f97316" stroke-width="2" fill="none" marker-end="url(#ahh)"/>
155
- <path d="M390,150 C430,150 430,170 466,170" stroke="#f97316" stroke-width="2" fill="none" marker-end="url(#ahh)"/>
156
- <path d="M390,165 C430,190 430,255 466,258" stroke="#a855f7" stroke-width="2" fill="none" marker-end="url(#ahg)"/>
157
- <path d="M650,215 L650,232" stroke="#a855f7" stroke-width="2" fill="none" marker-end="url(#ahg)"/>
158
- <path d="M845,170 C880,170 880,250 845,335" stroke="#a855f7" stroke-width="2" fill="none" marker-end="url(#ahg)" />
159
- <text x="862" y="260" fill="#d8b4fe" font-size="11.5">gen</text>
160
-
161
- <!-- callers -->
162
- <rect x="900" y="45" width="280" height="170" rx="8" fill="#171b21" stroke="#2a313b"/>
163
- <text x="916" y="70" fill="#e6e9ee" font-size="14" font-weight="600">21 Rust call sites</text>
164
- <text x="916" y="92" fill="#cfd5de" font-size="12.5">physics/car.rs, training/*.rs,</text>
165
- <text x="916" y="110" fill="#cfd5de" font-size="12.5">track/curve.rs, random_track.rs …</text>
166
- <text x="916" y="134" fill="#cfd5de" font-size="12.5">call native_math::atan2(...) etc.</text>
167
- <text x="916" y="158" fill="#cfd5de" font-size="12.5">gpu/sim step/sensors/stats/track.h</text>
168
- <text x="916" y="176" fill="#cfd5de" font-size="12.5">call native_* / dexp / dpow</text>
169
- <text x="916" y="200" fill="#fca5a5" font-size="12.5">→ no way to choose a platform</text>
170
-
171
- <!-- problems box -->
172
- <rect x="20" y="240" width="420" height="215" rx="8" fill="#2a1416" stroke="#ef4444"/>
173
- <text x="36" y="266" fill="#fecaca" font-size="15" font-weight="600">Limits for issue #7</text>
174
- <text x="36" y="292" fill="#fca5a5" font-size="13">• One implementation per function, compiled in.</text>
175
- <text x="36" y="314" fill="#fca5a5" font-size="13">• Rust and HIP are two hand-maintained sources;</text>
176
- <text x="48" y="332" fill="#fca5a5" font-size="13">AVX2 is a third for tanh.</text>
177
- <text x="36" y="354" fill="#fca5a5" font-size="13">• FMA is forbidden everywhere (contract=off);</text>
178
- <text x="48" y="372" fill="#fca5a5" font-size="13">no explicit fma primitive in Rust/HIP/WGSL code.</text>
179
- <text x="36" y="394" fill="#fca5a5" font-size="13">• Golden fixtures describe Proton only.</text>
180
- <text x="36" y="416" fill="#fca5a5" font-size="13">• Adding Windows naïvely = 22 × (Rust + HIP)</text>
181
- <text x="48" y="434" fill="#fca5a5" font-size="13">+ 3 AVX2 bit-exact hand ports.</text>
182
-
183
- <!-- legend -->
184
- <rect x="470" y="410" width="12" height="12" fill="#f97316"/><text x="488" y="421" fill="#98a2b3" font-size="12.5">hand-written port</text>
185
- <rect x="610" y="410" width="12" height="12" fill="#a855f7"/><text x="628" y="421" fill="#98a2b3" font-size="12.5">generated</text>
186
- <rect x="720" y="410" width="12" height="12" fill="#3b82f6"/><text x="738" y="421" fill="#98a2b3" font-size="12.5">source of truth</text>
187
- </svg>
188
- </div>
189
- <p class="caption">Rust is the reference; HIP is a second hand-written copy; WGSL is generated from HIP; AVX2 has a third copy of tanh. Each backend's math is fixed when it is compiled.</p>
190
-
191
- <h2>3. Proposed architecture</h2>
192
- <div class="figure">
193
- <svg viewBox="0 0 1200 760" width="100%" role="img" aria-label="Proposed architecture">
194
- <defs>
195
- <marker id="a2" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#a855f7"/></marker>
196
- <marker id="a3" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#22c55e"/></marker>
197
- <marker id="a4" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#98a2b3"/></marker>
198
- </defs>
199
-
200
- <!-- Layer labels -->
201
- <text x="20" y="26" fill="#98a2b3" font-size="13">① EVIDENCE (dev-only, Wine)</text>
202
- <text x="330" y="26" fill="#98a2b3" font-size="13">② SINGLE SOURCE</text>
203
- <text x="690" y="26" fill="#98a2b3" font-size="13">③ GENERATED BACKENDS</text>
204
- <text x="990" y="26" fill="#98a2b3" font-size="13">④ RUNTIME SELECTION</text>
205
-
206
- <!-- Evidence -->
207
- <rect x="20" y="40" width="280" height="250" rx="8" fill="#171b21" stroke="#2a313b"/>
208
- <text x="36" y="64" fill="#e6e9ee" font-size="14" font-weight="600">UCRT reference harness</text>
209
- <text x="36" y="86" fill="#cfd5de" font-size="12.5">tools/ucrt-ref (from ucrt_harness.c)</text>
210
- <text x="36" y="104" fill="#cfd5de" font-size="12.5">genuine DLL × FMA3 on/off, under Wine</text>
211
- <text x="36" y="130" fill="#e6e9ee" font-size="13" font-weight="600">Outputs (committed):</text>
212
- <text x="36" y="150" fill="#cfd5de" font-size="12.5">• golden vectors per profile</text>
213
- <text x="48" y="168" fill="#cfd5de" font-size="12.5">tests/fixtures/math_profiles/*.bin</text>
214
- <text x="36" y="188" fill="#cfd5de" font-size="12.5">• exhaustive sinf/cosf scans</text>
215
- <text x="48" y="206" fill="#cfd5de" font-size="12.5">→ exception tables</text>
216
- <text x="36" y="226" fill="#cfd5de" font-size="12.5">• build → profile map (profiles.toml)</text>
217
- <text x="36" y="252" fill="#fcd34d" font-size="12.5">DLLs are never committed;</text>
218
- <text x="36" y="270" fill="#fcd34d" font-size="12.5">only versions, hashes and output bits.</text>
219
-
220
- <!-- Single source -->
221
- <rect x="330" y="40" width="330" height="330" rx="8" fill="#14243f" stroke="#3b82f6"/>
222
- <text x="346" y="64" fill="#e6e9ee" font-size="14" font-weight="600">math/kernels/ (restricted C subset)</text>
223
- <text x="346" y="86" fill="#93c5fd" font-size="12.5">the subset gen-sim.py already parses</text>
224
- <rect x="346" y="98" width="298" height="122" rx="6" fill="#0f1a2e" stroke="#2b4a7a"/>
225
- <text x="358" y="118" fill="#cfd5de" font-size="12.5">musl/ sinf cosf atan2f exp log pow tanh</text>
226
- <text x="358" y="138" fill="#cfd5de" font-size="12.5">ucrt/ atan2f log</text>
227
- <text x="358" y="158" fill="#cfd5de" font-size="12.5">ucrt/ exp_{a_fma,b_fma,sse2}</text>
228
- <text x="358" y="178" fill="#cfd5de" font-size="12.5">ucrt/ pow_{a_fma,a_sse2,b_fma,b_sse2}</text>
229
- <text x="358" y="198" fill="#cfd5de" font-size="12.5">ucrt/ tanh_{a,b_fma} sincos = musl + table</text>
230
- <text x="346" y="244" fill="#e6e9ee" font-size="13" font-weight="600">Primitives every backend must provide</text>
231
- <text x="346" y="264" fill="#cfd5de" font-size="12.5">add/sub/mul/div (correctly rounded),</text>
232
- <text x="346" y="282" fill="#cfd5de" font-size="12.5">fma() explicit and exact, bits casts, select()</text>
233
- <text x="346" y="306" fill="#e6e9ee" font-size="13" font-weight="600">profiles.toml</text>
234
- <text x="346" y="326" fill="#cfd5de" font-size="12.5">profile → variant per function (the matrix in §1)</text>
235
- <text x="346" y="346" fill="#cfd5de" font-size="12.5">+ the UCRT builds each profile stands for</text>
236
-
237
- <!-- Generator -->
238
- <rect x="330" y="400" width="330" height="80" rx="8" fill="#1f1530" stroke="#a855f7"/>
239
- <text x="346" y="424" fill="#e6e9ee" font-size="14" font-weight="600">wasm/gen-math.py</text>
240
- <text x="346" y="446" fill="#d8b4fe" font-size="12.5">reuses gen-sim.py's pycparser front end;</text>
241
- <text x="346" y="464" fill="#d8b4fe" font-size="12.5">4 emitters; CI runs it with --check</text>
242
- <path d="M495,370 L495,396" stroke="#a855f7" stroke-width="2" marker-end="url(#a2)"/>
243
-
244
- <!-- evidence -> source -->
245
- <path d="M300,190 L326,190" stroke="#98a2b3" stroke-width="2" marker-end="url(#a4)"/>
246
-
247
- <!-- Backends -->
248
- <g>
249
- <rect x="690" y="40" width="270" height="78" rx="8" fill="#1f1530" stroke="#a855f7"/>
250
- <text x="706" y="64" fill="#e6e9ee" font-size="14" font-weight="600">Rust scalar (+ WASM CPU)</text>
251
- <text x="706" y="84" fill="#d8b4fe" font-size="12.5">src/math/platform/generated.rs</text>
252
- <text x="706" y="102" fill="#d8b4fe" font-size="12.5">fma → f64::mul_add (always exact)</text>
253
-
254
- <rect x="690" y="132" width="270" height="78" rx="8" fill="#1f1530" stroke="#a855f7"/>
255
- <text x="706" y="156" fill="#e6e9ee" font-size="14" font-weight="600">AVX2 (tanh variants only)</text>
256
- <text x="706" y="176" fill="#d8b4fe" font-size="12.5">emitted from branch-free kernels</text>
257
- <text x="706" y="194" fill="#d8b4fe" font-size="12.5">fma → _mm256_fmadd_pd / scalar fallback</text>
258
-
259
- <rect x="690" y="224" width="270" height="78" rx="8" fill="#1f1530" stroke="#a855f7"/>
260
- <text x="706" y="248" fill="#e6e9ee" font-size="14" font-weight="600">HIP</text>
261
- <text x="706" y="268" fill="#d8b4fe" font-size="12.5">gpu/sim/platform_math.h (#include)</text>
262
- <text x="706" y="286" fill="#d8b4fe" font-size="12.5">fma → __fma_rn; contract stays off</text>
263
-
264
- <rect x="690" y="316" width="270" height="96" rx="8" fill="#1f1530" stroke="#a855f7"/>
265
- <text x="706" y="340" fill="#e6e9ee" font-size="14" font-weight="600">WGSL, one module per profile</text>
266
- <text x="706" y="360" fill="#d8b4fe" font-size="12.5">src/wasm/sim/math_&lt;profile&gt;.wgsl</text>
267
- <text x="706" y="378" fill="#d8b4fe" font-size="12.5">fma → new f64_fma in f64.wgsl,</text>
268
- <text x="706" y="396" fill="#d8b4fe" font-size="12.5">f32 fma via exact f64 product</text>
269
- </g>
270
- <path d="M660,440 C690,440 670,80 686,80" stroke="#a855f7" stroke-width="2" fill="none" marker-end="url(#a2)"/>
271
- <path d="M660,440 C690,440 672,172 686,172" stroke="#a855f7" stroke-width="2" fill="none" marker-end="url(#a2)"/>
272
- <path d="M660,440 C690,440 674,264 686,264" stroke="#a855f7" stroke-width="2" fill="none" marker-end="url(#a2)"/>
273
- <path d="M660,440 C690,440 676,364 686,364" stroke="#a855f7" stroke-width="2" fill="none" marker-end="url(#a2)"/>
274
-
275
- <!-- Runtime selection -->
276
- <rect x="990" y="40" width="190" height="372" rx="8" fill="#12261a" stroke="#22c55e"/>
277
- <text x="1004" y="64" fill="#e6e9ee" font-size="14" font-weight="600">MathProfile</text>
278
- <text x="1004" y="86" fill="#bbf7d0" font-size="12.5">proton | win10-fma3 |</text>
279
- <text x="1004" y="104" fill="#bbf7d0" font-size="12.5">win10-sse2 | win11-fma3 |</text>
280
- <text x="1004" y="122" fill="#bbf7d0" font-size="12.5">win11-sse2</text>
281
- <text x="1004" y="150" fill="#e6e9ee" font-size="12.5" font-weight="600">SessionOptions</text>
282
- <text x="1004" y="168" fill="#bbf7d0" font-size="12.5">mathProfile (default proton)</text>
283
- <text x="1004" y="192" fill="#e6e9ee" font-size="12.5" font-weight="600">Checkpoint header</text>
284
- <text x="1004" y="210" fill="#bbf7d0" font-size="12.5">records profile; resume</text>
285
- <text x="1004" y="228" fill="#bbf7d0" font-size="12.5">rejects a mismatch</text>
286
- <text x="1004" y="252" fill="#e6e9ee" font-size="12.5" font-weight="600">Rust</text>
287
- <text x="1004" y="270" fill="#bbf7d0" font-size="12.5">Math{profile} passed to</text>
288
- <text x="1004" y="288" fill="#bbf7d0" font-size="12.5">world/runner; 21 sites call</text>
289
- <text x="1004" y="306" fill="#bbf7d0" font-size="12.5">m.atan2(), m.exp() …</text>
290
- <text x="1004" y="330" fill="#e6e9ee" font-size="12.5" font-weight="600">HIP</text>
291
- <text x="1004" y="348" fill="#bbf7d0" font-size="12.5">wave-uniform profile arg</text>
292
- <text x="1004" y="372" fill="#e6e9ee" font-size="12.5" font-weight="600">WebGPU</text>
293
- <text x="1004" y="390" fill="#bbf7d0" font-size="12.5">concat chosen module only</text>
294
- <path d="M960,80 L986,80" stroke="#22c55e" stroke-width="2" marker-end="url(#a3)"/>
295
- <path d="M960,172 L986,172" stroke="#22c55e" stroke-width="2" marker-end="url(#a3)"/>
296
- <path d="M960,264 L986,264" stroke="#22c55e" stroke-width="2" marker-end="url(#a3)"/>
297
- <path d="M960,364 L986,364" stroke="#22c55e" stroke-width="2" marker-end="url(#a3)"/>
298
-
299
- <!-- Verification band -->
300
- <rect x="20" y="510" width="1160" height="230" rx="8" fill="#171b21" stroke="#22c55e" stroke-dasharray="5 4"/>
301
- <text x="36" y="536" fill="#e6e9ee" font-size="15" font-weight="600">⑤ Verification matrix (every profile × every backend, bit-exact)</text>
302
- <g font-size="12.5">
303
- <rect x="36" y="552" width="260" height="170" rx="6" fill="#0f1a14" stroke="#1f5133"/>
304
- <text x="50" y="574" fill="#e6e9ee" font-weight="600">Math level</text>
305
- <text x="50" y="596" fill="#bbf7d0">Golden vectors vs. Rust scalar</text>
306
- <text x="50" y="616" fill="#bbf7d0">and AVX2 (cargo test).</text>
307
- <text x="50" y="640" fill="#bbf7d0">HIP math_kernel op tests</text>
308
- <text x="50" y="660" fill="#bbf7d0">gain a profile argument.</text>
309
- <text x="50" y="684" fill="#bbf7d0">WGSL: wasm/test/exact.js</text>
310
- <text x="50" y="704" fill="#bbf7d0">over the same vectors.</text>
311
-
312
- <rect x="316" y="552" width="260" height="170" rx="6" fill="#0f1a14" stroke="#1f5133"/>
313
- <text x="330" y="574" fill="#e6e9ee" font-weight="600">Exhaustive (f32 unary)</text>
314
- <text x="330" y="596" fill="#bbf7d0">All 2³² inputs for sinf/cosf</text>
315
- <text x="330" y="616" fill="#bbf7d0">per variant: musl + table</text>
316
- <text x="330" y="636" fill="#bbf7d0">== genuine DLL. Ignored test,</text>
317
- <text x="330" y="656" fill="#bbf7d0">runs under Wine (~45 s/pair),</text>
318
- <text x="330" y="676" fill="#bbf7d0">like examples/</text>
319
- <text x="330" y="694" fill="#bbf7d0">gpu_engine_scan.rs.</text>
320
-
321
- <rect x="596" y="552" width="260" height="170" rx="6" fill="#0f1a14" stroke="#1f5133"/>
322
- <text x="610" y="574" fill="#e6e9ee" font-weight="600">Simulation level</text>
323
- <text x="610" y="596" fill="#bbf7d0">Existing CPU↔HIP↔WebGPU</text>
324
- <text x="610" y="616" fill="#bbf7d0">parity tests, parameterised</text>
325
- <text x="610" y="636" fill="#bbf7d0">by profile. proton goldens</text>
326
- <text x="610" y="656" fill="#bbf7d0">must stay byte-identical</text>
327
- <text x="610" y="676" fill="#bbf7d0">(refactor guard).</text>
328
-
329
- <rect x="876" y="552" width="290" height="170" rx="6" fill="#0f1a14" stroke="#1f5133"/>
330
- <text x="890" y="574" fill="#e6e9ee" font-weight="600">Game level (optional)</text>
331
- <text x="890" y="596" fill="#bbf7d0">Windows player records a trace</text>
332
- <text x="890" y="616" fill="#bbf7d0">via the game's MCP server; the</text>
333
- <text x="890" y="636" fill="#bbf7d0">sim replays it under each profile.</text>
334
- <text x="890" y="656" fill="#bbf7d0">The matching profile confirms the</text>
335
- <text x="890" y="676" fill="#bbf7d0">setup end to end and can</text>
336
- <text x="890" y="696" fill="#bbf7d0">auto-detect a user's profile.</text>
337
- </g>
338
- <path d="M600,412 L600,505" stroke="#22c55e" stroke-width="2" stroke-dasharray="4 3" marker-end="url(#a3)"/>
339
- </svg>
340
- </div>
341
- <p class="caption">One source per variant, four generated backends, and the profile chosen at run time. The Wine harness that produced the survey becomes the permanent oracle.</p>
342
-
343
- <h2>4. Current vs proposed</h2>
344
- <table>
345
- <tr><th style="width:18%">Concern</th><th style="width:41%">Current</th><th>Proposed</th></tr>
346
- <tr><td>Platform choice</td><td class="bad">Fixed at compile time: Proton/musl only</td><td class="good"><code>MathProfile</code> chosen per session and recorded in checkpoints; default <code>proton</code></td></tr>
347
- <tr><td>Sources of truth</td><td>Rust (reference) + HIP (hand copy) + AVX2 tanh (hand copy)</td><td>One C-subset kernel per variant; Rust, AVX2, HIP and WGSL are generated</td></tr>
348
- <tr><td>Cost of one new variant</td><td class="bad">Up to 3 bit-exact hand ports + regenerate WGSL + new fixtures</td><td class="good">1 kernel + 1 line in <code>profiles.toml</code> + regenerated golden vectors</td></tr>
349
- <tr><td>FMA</td><td>Forbidden everywhere (<code>-ffp-contract=off</code>); no fma primitive</td><td>Still no implicit contraction; an explicit <code>fma()</code> primitive with an exact implementation on each backend</td></tr>
350
- <tr><td>sinf / cosf</td><td>musl port</td><td>musl port + per-variant exception table (6–51k entries), proven over every float32</td></tr>
351
- <tr><td>atan2f, exp, log, pow, tanh</td><td>musl ports</td><td>musl + UCRT algorithm ports (can't be proven exhaustively; validated with golden vectors)</td></tr>
352
- <tr><td>HIP selection</td><td>n/a</td><td>Profile kernel argument (uniform per launch, so no divergence); template instantiation only if profiling shows register pressure</td></tr>
353
- <tr><td>WebGPU selection</td><td>n/a</td><td>Assemble the shader with only the chosen <code>math_&lt;profile&gt;.wgsl</code>, keeping compile cost flat</td></tr>
354
- <tr><td>Track generation</td><td>Uses <code>atan2f</code> (random_track.rs, curve.rs)</td><td>Uses the profile too, so generated geometry matches the player's platform</td></tr>
355
- <tr><td>Fixtures</td><td>Proton captures only</td><td>Proton captures unchanged + per-profile golden vectors from genuine DLLs (outputs only)</td></tr>
356
- <tr><td>Unaffected</td><td colspan="2">x87 <code>engine_sin_cos</code>, .NET <code>managed_sin_cos</code>, all ordinary arithmetic, RNG streams, and <code>pyrandom</code>'s host libm (separate CPython-compat concern)</td></tr>
357
- </table>
358
-
359
- <h2>5. Implementation strategy per function</h2>
360
- <table>
361
- <tr><th>Function</th><th>Approach</th><th>Why</th><th>Proof level</th></tr>
362
- <tr><td>sinf, cosf</td><td>musl kernel + sorted exception table + branch-free binary search (existing <code>engine_sin_cos</code> pattern)</td><td>Only 6,254–50,872 of 2³² inputs differ, all 1 ULP; the table is generated from the scan</td><td class="good">Exhaustive</td></tr>
363
- <tr><td>atan2f</td><td>Port the UCRT algorithm</td><td>16% of inputs differ, too many for a table, and there are 2 arguments</td><td>Golden vectors</td></tr>
364
- <tr><td>tanh</td><td>Port both UCRT variants in branch-free form (also feeds AVX2)</td><td>About 10% of inputs differ; it's the hottest path (inference)</td><td>Golden vectors</td></tr>
365
- <tr><td>exp, pow, log</td><td>Port UCRT algorithms; FMA and SSE2 variants differ only where <code>fma()</code> is used</td><td>Double-precision inputs can't be enumerated</td><td>Golden vectors</td></tr>
366
- </table>
367
-
368
- <h2>6. Phased rollout</h2>
369
- <ol class="phases">
370
- <li><b>Phase 0: spike (decides feasibility).</b> Recover the algorithms behind UCRT <code>atan2f</code> and <code>tanh</code>, the two highest-impact functions, and reproduce the golden vectors bit-exactly in a throwaway Rust prototype. Turn <code>ucrt_harness.c</code> and the 56-build survey into <code>tools/ucrt-ref</code>. <i>Exit criterion:</i> 0 differences on golden vectors for both functions on both paths.</li>
371
- <li><b>Phase 1: plumbing, no behaviour change.</b> Add <code>MathProfile</code>, <code>SessionOptions.mathProfile</code> and the checkpoint field; route the 21 Rust call sites and the HIP/WGSL call sites through a profile-aware layer that still only knows <code>proton</code>. All existing goldens stay byte-identical.</li>
372
- <li><b>Phase 2: single source, no behaviour change.</b> Move the musl kernels into <code>math/kernels/</code>, write <code>gen-math.py</code> with Rust/AVX2/HIP/WGSL emitters, and replace the hand ports with generated code. Guard: exhaustive f32 checks and fixture checks against the old code.</li>
373
- <li><b>Phase 3: Windows variants.</b> Add them in order of impact: atan2f, tanh, exp, pow, log, then the sin/cos tables. Add <code>f64_fma</code> to <code>f64.wgsl</code> and the scalar fma fallback for CPUs without FMA.</li>
374
- <li><b>Phase 4: parity matrix.</b> Parameterise CPU↔HIP↔WebGPU parity and session regressions by profile; run the full set for <code>proton</code> and one Windows profile in CI, all profiles nightly.</li>
375
- <li><b>Phase 5: user-facing.</b> Profile picker in Drive Lab and the CLI (<code>--math-profile</code>), with a short "which one am I?" helper (Windows version, FMA3 support); optional detection from a recorded game trace.</li>
376
- </ol>
377
-
378
- <h2>7. Risks and open questions</h2>
379
- <div class="grid2">
380
- <div class="card">
381
- <h3>Deriving the UCRT algorithms <span class="tag">largest risk</span></h3>
382
- <p>For atan2f, exp, log, pow and tanh we need Microsoft's actual algorithm, not just its outputs. Studying the binary may conflict with Microsoft's licence terms, and interoperability exceptions vary by jurisdiction, so <b>this needs a decision before Phase 0</b>. Black-box fitting against golden vectors is a fallback, but it may not converge to bit-exactness. One unverified hypothesis: the x64 CRT's transcendentals may share ancestry with AMD's open-source libm. If so, that would be a clean starting point to test against the vectors.</p>
383
- </div>
384
- <div class="card">
385
- <h3>Coverage the survey didn't test</h3>
386
- <ul>
387
- <li>All results came from one CPU (Zen 4 with AVX-512). It's unknown whether newer builds use AVX-512 paths that CPUs without AVX-512 wouldn't take.</li>
388
- <li>FMA3 vs SSE2 was forced with <code>_set_FMA3_enable</code>, not observed on a CPU without FMA3.</li>
389
- <li>Windows on ARM (x64 emulation) wasn't tested.</li>
390
- <li>Profiles may need splitting if any of these show differences; <code>profiles.toml</code> makes that a data change.</li>
391
- </ul>
392
- </div>
393
- <div class="card">
394
- <h3>Performance</h3>
395
- <ul>
396
- <li>FMA3 profiles on targets without hardware FMA: <code>f64::mul_add</code> on WASM and pre-Haswell CPUs, and <code>f64_fma</code> in WGSL soft-float, are much slower than a multiply plus an add. This mainly affects tanh in inference.</li>
397
- <li>The per-call profile <code>match</code> in Rust should be close to free (well predicted); switch to monomorphisation only if benchmarks show otherwise.</li>
398
- <li>HIP code size grows with the number of inlined variants. Watch register pressure and occupancy.</li>
399
- </ul>
400
- </div>
401
- <div class="card">
402
- <h3>Scope and maintenance</h3>
403
- <ul>
404
- <li>About 3× more kernels (22 vs 7), but each is written once.</li>
405
- <li>Golden vectors grow per profile: keep about 64k inputs per function per profile, so a few MB total.</li>
406
- <li>A future UCRT update can add a behaviour group. The survey script reruns in about 2 minutes against Winbindex, so it can become a periodic check.</li>
407
- <li>An end-to-end game confirmation still needs a Windows player's trace (Steam blocks running outside Steam).</li>
408
- </ul>
409
- </div>
410
- </div>
411
-
412
- <p class="caption" style="margin-top:28px">Sources: code at <code>e96a2e8</code> (src/math, src/nn, gpu/sim, wasm/gen-sim.py, src/wasm/sim); UCRT survey data in <code>~/altd-wine/versions/</code> (sweep.json, groupcmp_*.txt, exhaustive_*.txt).</p>
413
- </main>
414
- </body>
415
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
github-simulator/source/docs/performance.md DELETED
@@ -1,72 +0,0 @@
1
- # Performance measurements
2
-
3
- All timings below describe the stated hardware and inputs. Generated-track benchmarks in this tree provide a repeatable public workload; historical campaign/checkpoint measurements are retained for context and cannot be reproduced from public assets alone.
4
-
5
- ## Native CPU baseline
6
-
7
- Measured on an AMD Ryzen 9 7950X, Linux x86_64, rustc 1.94 and LLVM 21.1.8, with local `target-cpu=native`. Each workload had an untimed warmup and seven measured samples. Worker processes used eight distinct physical cores. Desktop activity and a concurrent GPU training process remained active.
8
-
9
- The fixed bench workloads used 1,024 cars, 3,600 timed ticks, two warmup ticks, a fixed seed/network/model and independent execution. The generated scene used seed 1729, generation zero, slot zero. The random batch used 512 cars, three generations, three tracks per generation, 3,600 ticks per track and eight workers. Random timing includes simulation, turnover and track installation waits. Throughput uses the requested car-tick count; elimination can reduce actual executed work.
10
-
11
- | Workload | Workers | Median seconds | Requested car-ticks/s |
12
- | --- | ---: | ---: | ---: |
13
- | Captured campaign scene | 1 | 7.474565 | 493,193 |
14
- | Captured campaign scene | 8 | 0.987717 | 3,732,242 |
15
- | Generated scene | 1 | 7.508362 | 490,973 |
16
- | Generated scene | 8 | 1.004230 | 3,670,872 |
17
- | Random training batch | 8 | 4.673350 | 3,549,660 |
18
-
19
- An identical-source repeat changed the medians by -0.15%, -0.95%, +0.06%, -2.33% and -0.37%, respectively. This measures noise; it is not a speedup claim. Public benchmark recipes use different generated geometry and Xavier weights, so their numbers need their own baseline.
20
-
21
- ```sh
22
- cargo build --release --offline
23
- python3 tools/benchmark.py --population 1024 --ticks 3600 --repeats 7 \
24
- --threads 1 8 --report target/cpu-benchmark.json
25
- ```
26
-
27
- The runner works from any directory, keeps every JSON sample and reports medians. `--scene`, `--spawn-trace`, `--network`, `--model`, `--modes` and `--binary` select another workload. It measures the CLI simulation interval; process launch, loading and the initial population are outside that interval.
28
-
29
- ## Historical HIP measurements
30
-
31
- AMD Radeon RX 7900 XTX, gfx1100, HIP 7.1.52802, ROCm clang 20 and Ryzen 9 7950X with eight Rayon workers. Inputs were a captured Rally campaign scene and a frozen 8,192-network checkpoint, repeated for larger populations. Shape was `20,16,16,16,16,12,12,8,5`, with 1,661 double parameters per car and two inference batches. The desktop remained active.
32
-
33
- Full generation medians after one warmup and three measured runs were 2.094 seconds at 8,192 cars, 5.715 at 32,768 and 40.315 at 262,144. Wall and idle elimination were disabled; the 5,400-tick limit ended at statistics callback 5,406. Timers included packing, transfers, simulation and state import, and excluded reset, hashing, reproduction and checkpoint I/O. A later kernel investigation recorded production wall times of about 1.86, 4.93 and 36.2 seconds with unchanged digests, but did not record the same repeated-median protocol. Treat those later values as diagnostic observations.
34
-
35
- Separate turnover optimization measurements used three consecutive generations with elimination enabled, one warmup and three timed samples. Complete-generation medians changed from 0.386 to 0.267 seconds at 8,192 cars, 1.154 to 0.790 at 32,768 and 9.663 to 6.336 at 262,144. They include turnover after the third generation and exclude loading, hashing and checkpoint I/O. All 36 before/after generation pairs matched result digests and executed ticks. This workload ended early and must not be compared as a full 5,400-tick run.
36
-
37
- Use [GPU tooling](../gpu/README.md) for fresh measurements on generated inputs. A GPU performance gate requires an otherwise idle GPU; these historical results do not establish throughput under concurrent training load.
38
-
39
- ## Historical browser measurements
40
-
41
- Ryzen 9 7950X, Chromium 153.0.8010.12 on Linux, RX 7900 XTX with RADV 26.2.2. A Formula scene used shape `20,16,5`, two inference batches and no elimination. Four 180-tick generations ran per population; the first was warmup and the median of the next three is shown. Complete time includes evolution and coordinator yields. This was one sweep.
42
-
43
- | Cars | Serial complete ms | Eight-worker complete ms | WebGPU with eight workers ms |
44
- | --- | ---: | ---: | ---: |
45
- | 32 | 12.7 | 4.9 | 365.2 |
46
- | 256 | 100.4 | 18.3 | 361.5 |
47
- | 1,024 | 399.5 | 66.1 | 189.0 |
48
- | 4,096 | 1,657.3 | 263.8 | 647.7 |
49
-
50
- At 4,096 cars, eight-worker CPU advancement took 228.9 ms versus 1,577.7 ms serial. Module/pool startup was 14.1 ms serial and 94.5 ms with eight workers. Peak observed linear memory in the largest case was 97.6 MiB serial and 113.7 MiB with eight workers, excluding JavaScript workers, GPU allocations and any separate preview module. These inputs are historical; rerun the [public browser harness](../wasm/README.md) to establish results for the generated scenarios and another browser/device.
51
-
52
- ## Firefox completion waits — 2026-10-06
53
-
54
- Firefox 157 on the local Linux/RX 7900 XTX system reproduced the 30 ticks/s limit. In the public Formula benchmark, six-tick calls took about 200 ms at both 32 and 1,024 cars. At 32 cars, the 120 measured ticks spent 3,975 ms in advancement while GPU timestamps covered only 192 ms. Setting GPU load to 1 retained the same limit, ruling out the configured idle budget as its cause.
55
-
56
- The runtime now prompts completion delivery with empty queue submissions every 4 ms while awaiting queued work or mapped readback. It retains the original promises and command order, cancelling the timer after completion, device loss or a submission exception. The earlier workaround was absent from this source tree. The Windows/Proton kernel sources are unchanged by this fix.
57
-
58
- | Workload | Cars | Before ticks/s | After ticks/s |
59
- | --- | ---: | ---: | ---: |
60
- | Formula, fixed six-tick windows | 32 | 30.19 | 688.07 |
61
- | Formula, fixed six-tick windows | 1,024 | 30.27 | 259.63 |
62
- | Normally served app, Rally, adaptive windows | 512 | 29.98 | 249.53 |
63
-
64
- Formula used the public default scenario, shape `20,16,5`, Proton, disabled elimination and 120 warmup ticks, with 120 measured ticks at 32 cars and 60 at 1,024 cars. The benchmark records per-pass GPU timestamps. The app used its Test Loop fixture, default shape `20,16,16,12,8,5`, one inference batch, eight CPU workers, Proton, load 0.85 and disabled elimination. App values are medians of the reported rates during a four-second observation; whole-observation rates were 29.88 and 258.92 ticks/s. The final served run used the rebuilt assets without package or runtime overrides. Compilation and startup are excluded. These are diagnostic before/after observations, not repeated benchmark medians.
65
-
66
- A separate app comparison completed three generations and 558 ticks with each runtime, using identical rebuilt WASM packages and changing only the JavaScript completion waits. Checkpoint bytes, every population network, terminal car states, summaries and stable generation logs matched exactly. The completed outcome SHA-256 was `7086f0ce5b7f555d7bc2d7a4ef5c2db321d71ebb3c21dd93eaa9324ffa02eedc`. Time through the third turnover changed from 18,688 ms to 1,405 ms; the adaptive pump used 90 calls before and 37 after.
67
-
68
- Two additional runs through normally served assets completed the same 558 ticks in 2,339 and 2,385 ms, with identical outcomes and stable logs. A prior diagnostic run with package routing reported 1,143 ticks/s; the normal served measurements above provide the conservative result. One initial instrumented run stalled while waiting for its generation outcome. Its detailed phase was not captured, and the stall did not recur in the three subsequent completed comparisons; its cause remains unresolved.
69
-
70
- Three alternating Chromium 153 comparisons kept the WASM, shader, Win11 profile, 1,024 active cars and 120-tick bulk windows identical, changing only the completion-wait runtime. Median wall time was 355.4 ms before and 355.0 ms after. Background GPU activity was present before browser launches, so these observations do not measure isolated peak throughput.
71
-
72
- Both serial and threaded production packages were rebuilt. Full Firefox simulation comparisons passed for all three profiles: 184,558 checks, zero mismatches. The Node completion-wait regression suite passes 16 tests against the fixed runtime; the frozen original runtime fails nine of them. See [the browser commands](../wasm/README.md) to repeat the Formula workload or run the regression suite without a GPU.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
github-simulator/source/docs/reviews/2026-10-05-native-server-review.md DELETED
@@ -1,51 +0,0 @@
1
- # Native server implementation review
2
-
3
- Date: 2026-10-05
4
-
5
- Two independent reviewers used GPT-6.1-sol at ultra effort. The native comparison starts at `origin/main`, commit `0852de991c6e6e2d9868f74346bb0ac9d3260774`. The companion webapp comparison starts at `aebb7ab` and ends at `e99e65541cb502302a32ac2d1bdc4d53b9aee0a9`, branch `t3code/native-simulator-client`. The webapp repository has no configured remote.
6
-
7
- The spec is [the approved native server design](../superpowers/specs/2026-10-05-native-server-design.md). Standards sources include `docs/design.md` and the code-review skill's code-smell baseline. The reviewers checked the implementation, then reviewed the fixes below.
8
-
9
- ## Standards
10
-
11
- The reviewer found no hard coding-standard violations or actionable code smells. The correctness review found that an ordinary HIP window error could panic and abort the release server. The new Session path returns errors from world creation, simulator creation, world replacement, network upload, state transfers and window execution. Unsupported scenes and networks fall back during initialization or verification.
12
-
13
- The follow-up review found leaked resources after partial GPU constructor failures. Constructors now retain ownership before copying and release partial allocations before returning null. World cleanup excludes borrowed host pointers; simulator cleanup leaves its borrowed World intact.
14
-
15
- The final review reports no remaining correctness findings, hard coding-standard violations or actionable code smells.
16
-
17
- ## Spec
18
-
19
- The reviewer found that a hidden layer wider than HIP's 16 inference lanes could abort the server rather than fall back. The HIP path now validates its network limits before upload; verification restores the initial runner state before CPU fallback. Real-socket regressions cover a 32-wide hidden layer and a scene without physics shapes.
20
-
21
- The device-name export was incorrectly mandatory. Older compatible libraries now probe device availability through the legacy math function and report the loaded library path. A real-socket HIP training test passed with a library that lacks the name export.
22
-
23
- The worker now ignores queued pause and resume commands after a run fails or finishes. A deterministic browser test injects an ordinary native RPC error, checks the saved failed state, and resumes from its checkpoint. Removing the guards makes that test fail.
24
-
25
- The final review confirms the constructor cleanup and fault-injection coverage, with no remaining high-confidence spec findings.
26
-
27
- ## Initial validation
28
-
29
- - Rust debug and release suites: 173 passed and five existing tests ignored in each.
30
- - Real-socket server suite: ten passed, including CPU parity, binary/JSON checkpoints, invalid requests, Origin/Host checks, HIP claim release and unsupported HIP fallback.
31
- - Actual RX 7900 XTX Session checks passed for CPU/HIP parity, restart, restore, track replacement, population growth and fallback.
32
- - Constructor cleanup passed all 38 World and 21 simulator injected failures, plus successful and null destruction. The same harness detects a leak in the previous library. ROCm CI runs it without a GPU.
33
- - Native and WASM Clippy, Rust 1.93 all-target compilation, formatting and rustdoc passed.
34
- - Serial and threaded WASM builds passed. CPU reference comparison checked 2,773 values with zero mismatches.
35
- - Webapp build, TypeScript, 31 unit tests, immutable asset publication and formatting passed.
36
- - Full browser suite: 45 passed, five conditional tests skipped. All ten native integration cases passed.
37
- - Hardware WebGPU training, partial-window CPU fallback and contact/reproduction parity checks passed.
38
-
39
- Remaining findings: Standards 0; Spec 0. Native/WASM last-bit differences remain tracked in [issue #3](https://github.com/Zorro909/driving_sim_rs/issues/3).
40
-
41
- ## Size limits and platform follow-up
42
-
43
- The user requested removal of all size constraints for local simulator connections. The server now has no configured WebSocket frame or message ceiling. The companion frontend change is commit `432e7da` on `t3code/native-simulator-client`. Native settings bypass browser network, population, stage, file and checkpoint limits while retaining valid values and shared checkpoint field widths. Unsupported HIP shapes continue on native CPU.
44
-
45
- Large checkpoints, run metadata and imported tracks use 32 MiB IndexedDB chunks, with replacement and deletion in one transaction. Database version 4 closes older connections before writing the new format. Review found and fixed the unchunked track path, oversized plan edits after browser fallback, and incompatible readers in old tabs. Startup failures with no training history can restart when the local simulator returns.
46
-
47
- Both reviewers rereviewed these fixes with no remaining findings. The frontend build, TypeScript, formatting, 35 unit tests and immutable asset checks passed. The full browser suite passed 52 tests with five expected skips, including all 13 native cases and four storage cases. Storage regressions round-trip checkpoints, metadata and tracks above 127 MiB and check rollback, replacement, deletion and schema migration.
48
-
49
- Platform CI exposed x87 precision-dependent large-angle reduction on Windows, a host-specific Xavier checksum on macOS, and ARM default NaN signs. The fixes preserve captured bits rather than relax comparisons. The macOS Xavier oracle compares every parameter and RNG bit with same-host CPython. Session tests retain exact Linux GNU goldens and compare both execution modes with the legacy Runner on every host, including exact checkpoint replay.
50
-
51
- The final native release suite passed 176 tests with five existing tests ignored. All 35 vehicle tests passed under AArch64 QEMU after reproducing the macOS distance-sensor failure. Debug/release sensor checks and Darwin Clippy passed. Fresh serial/threaded WASM builds passed, with 2,773 CPU reference values and zero mismatches. The rebuilt frontend passed asset checks and all 13 native integration cases again.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
github-simulator/source/docs/server.md DELETED
@@ -1,102 +0,0 @@
1
- # Local simulator server
2
-
3
- `altd-sim serve` exposes native `Session` simulation over a WebSocket. A client can use Rayon CPU threads or request the AMD HIP backend. The server implements the protocol for Drive Lab's planned native client; the webapp integration is a separate change.
4
-
5
- The server owns one session per connection. Clients own run storage, checkpoints, logs, stage changes and mutation schedules. Closing the socket drops its session.
6
-
7
- ## Starting the server
8
-
9
- The default Cargo features include `server`. CPU use needs no ROCm installation. Build the HIP library separately using [the GPU guide](../gpu/README.md).
10
-
11
- ```sh
12
- cargo build --release --offline
13
- target/release/altd-sim --threads 8 serve
14
- target/release/altd-sim serve --port 47800 \
15
- --allow-origin http://127.0.0.1:5173
16
- ```
17
-
18
- | Flag | Default and effect |
19
- | --- | --- |
20
- | `--port N` | `47800`; binds only `127.0.0.1:N` |
21
- | `--allow-origin ORIGIN` | `https://drivinglab.jectrum.de`; repeat to allow several origins, replacing the default list |
22
- | `--threads N` | Global flag; sizes the Rayon pool shared by all CPU sessions, with CPU affinity as the default |
23
- | `--math-profile PROFILE` | Global flag; the math profile of sessions whose options name none. Without it, the server detects the profile of its own machine |
24
-
25
- Allowed origins use `http://host[:port]` or `https://host[:port]`, with an ASCII hostname or IP address. Startup normalizes scheme and host case, compresses IPv6 addresses, removes a trailing slash and omits default ports. Paths, credentials, query strings and fragments are rejected. Startup prints the listening URL, allowed origins, CPU thread count, HIP availability and the default math profile.
26
-
27
- ## Connection checks
28
-
29
- Connect to `ws://127.0.0.1:47800/v1`, substituting the configured port. The handshake returns HTTP 403 unless all checks pass:
30
-
31
- - The request path is `/v1`.
32
- - `Origin` is present and exactly matches an allowed origin. Different schemes or ports do not match; `null` is rejected.
33
- - `Host` names `127.0.0.1` or `localhost` with the listening port. Other hostnames are rejected to prevent DNS rebinding.
34
-
35
- There is no LAN binding, TLS or authentication token. These checks restrict browser callers; a local program can supply its own headers. At most 64 connections (including incomplete handshakes) may be active. Excess sockets are closed before spawning a worker. Handshake socket reads/writes time out after 5 seconds; established socket reads/writes after 10 minutes of blocked I/O. Long-running generation computation is not subject to those socket timeouts. Connection-worker spawn failures reject that connection while retaining the accept loop. Requests run in order on a dedicated connection thread, with no per-request timeout. Incoming frames and assembled messages are each limited to 64 MiB, including binary checkpoint headers/payloads. Equal limits allow a browser to send an admissible message in one frame: JavaScript WebSocket.send cannot select continuation framing. Larger messages must be split into protocol-level operations; fragmenting a message does not bypass its assembled limit. A rejected oversized frame/message closes only that connection. A generation may take minutes.
36
-
37
- ## Protocol 1
38
-
39
- The first frame is a JSON text greeting:
40
-
41
- ```json
42
- {"type":"hello","protocol":1,"version":"1.1.0","threads":8,"carStateStride":14,"carStateFields":["x","y","..."],"hip":{"available":true,"device":"AMD Radeon RX 7900 XTX","platform":"HIP"},"mathProfile":"proton","mathProfiles":["proton","win10-fma3","win11-fma3"]}
43
- ```
44
-
45
- Read `carStateStride` and `carStateFields` from the greeting rather than hard-coding them. The example's fields are abbreviated. `platform` is `"HIP"` for the AMD library and `"CUDA"` for the NVIDIA one. When HIP is unavailable, `hip` instead contains `{"available":false,"reason":"..."}`. Availability means the process opened the library and device; a particular session can still fall back to CPU. `mathProfile` is the default math profile and `mathProfiles` lists every profile a session can choose; [math profiles](../math/README.md) documents their runtime variants.
46
-
47
- Requests use an unsigned integer `id`, an operation name and optional `args`:
48
-
49
- ```json
50
- {"id":7,"op":"advance","args":{"ticks":180,"stopWhenInactive":true}}
51
- ```
52
-
53
- A successful reply contains the same `id`, its result in `ok` and the current `state`. An error reply contains `id` and `error`, without `state`.
54
-
55
- ```json
56
- {"id":7,"ok":180,"state":{"started":true,"generation":0,"tick":180,"population":256,"activeCount":256,"checkpointGeneration":0,"backend":"cpu","backendNote":null,"mathProfile":"proton"}}
57
- ```
58
-
59
- `checkpointGeneration` identifies the restorable generation boundary, or is `null` before starting. It need not describe the current tick. `backend` reports what actually runs; `backendNote` explains a CPU fallback. `mathProfile` is the session's math profile. Clients can queue requests and match replies by `id`.
60
-
61
- ### Operations
62
-
63
- | Operation | `args` | `ok` |
64
- | --- | --- | --- |
65
- | `create` | `scene`, `network`, `model` as JSON strings; optional `options` as a SessionOptions object | `{backend, backendNote, mathProfile}` |
66
- | `start` | None; seeds training from the `create` network export | `null` |
67
- | `startWithShape` | `shape` as an array of unsigned 32-bit integers | `null` |
68
- | `restoreCheckpointBytes` | Binary payload, no arguments required | `null` |
69
- | `restoreCheckpointJson` | `json` as a checkpoint JSON string | `null` |
70
- | `advance` | `ticks`, `stopWhenInactive` | Executed ticks |
71
- | `advanceGeneration` | `timeLimitTicks` | Executed ticks |
72
- | `nextGeneration` | None | `{preservedCount, rewards}` |
73
- | `setEvolutionSettings` | `json` as an evolution-settings JSON string; `algorithm` is `"ga"` or `"ars"` (see design notes) | `null` |
74
- | `replaceTrack` | `scene` as a scene JSON string | `null` |
75
- | `generationSummary` | None | `{bestIndex, bestScore, lapped, active, lapIndex, lapTime}`, optional `averageScore` and `worstScore` |
76
- | `networkJson` | `index` | Network JSON string |
77
- | `carStates` | None | Number of `f64` values, with a binary payload |
78
- | `checkpointBytes` | None | `null`, with a binary payload |
79
-
80
- Call `create` once, then start or restore before advancing. `options.backend` accepts `"cpu"`, the default, or `"hip"`. `options.mathProfile` accepts `"proton"`, `"win10-fma3"` or `"win11-fma3"` and defaults to the server's profile; checkpoints restore only into sessions of the profile they were made with. Other SessionOptions fields retain their regular defaults and unknown fields are rejected. A second successful `create` on the same connection is an error. Unknown operations and malformed JSON return errors while leaving the connection usable.
81
-
82
- `start` uses the export's `weights` and `biases` as the seed, matching `train-scratch --init-network` and the browser simulator. GA breeds mutations of that seed; ARS samples around it as its initial search point. Without weights, `start` draws a Xavier seed from `shape` (or `summary.shape`). Without either weights or a shape, use `startWithShape`. Malformed weighted exports return an error before starting and leave the connection usable.
83
-
84
- ### Binary frames
85
-
86
- `restoreCheckpointBytes` requests and `carStates` or `checkpointBytes` replies use a binary WebSocket frame:
87
-
88
- ```text
89
- [u32 little-endian JSON byte length][UTF-8 JSON header][raw payload]
90
- ```
91
-
92
- The header has the same request or reply shape as a text frame. `carStates` payloads contain little-endian `f64` values, grouped by the greeting's stride and field order. Checkpoint payloads use the shared Session checkpoint format. All other operations use text frames. Invalid binary framing closes the connection.
93
-
94
- ## HIP fallback and resume
95
-
96
- Only one session can hold the HIP device per process. Another HIP request runs on CPU with `backendNote: "another session is using the GPU"`. Library/device errors, native broadphase tracks and unsupported path sensors also cause CPU fallback with a reason. HIP requires physics shapes and at least two path points. Networks support up to 12 layers, 32 inputs and 16 neurons in each later layer; wider CPU networks fall back during verification.
97
-
98
- Before a HIP session's first driving window after a start or restore, it compares 12 ticks against CPU from the same state, then restores that state. A mismatch or verification error drops HIP and runs the requested window on CPU. Track replacement uploads the new world and repeats verification before driving. Read `state.backend` after advancing because it may change from the `create` result.
99
-
100
- HIP cars and agents stay on the device between windows; an `advance` or `advanceGeneration` reply reads back only the active car count. `generationSummary`, `carStates`, turnover, restores and track replacement read the population back into the CPU runner first; checkpoints are saved from the generation boundary and need no readback. Turnover breeds on CPU to retain the parent records in format-2 checkpoints, then uploads the new networks and cars on the next HIP window. HIP libraries without `altd_gpu_sim_active_count` read the population back after every window. Checkpoints can move between native CPU, HIP and WASM sessions. Native and WASM training have known last-bit differences, so continued training may diverge after switching engines.
101
-
102
- HIP errors after startup verification return request errors without retrying. The client should stop the run and resume from its last saved checkpoint. A closed connection loses the server's session; reconnect, create a new session and restore a saved checkpoint. Release builds use `panic = "abort"`, so a panic terminates the server and closes every connection.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
github-simulator/source/docs/superpowers/specs/2026-10-05-native-server-design.md DELETED
@@ -1,322 +0,0 @@
1
- # Native simulator server for Drive Lab
2
-
3
- Date: 2026-10-05
4
- Status: implemented and reviewed
5
-
6
- ## Goal
7
-
8
- Drive Lab (`driving_webapp_public`) trains in the browser on WASM, optionally with the WebGPU raycaster, and that stays the default. Users who also run the native `altd-sim` binary should be able to train faster with it: on native CPU threads without the browser's 8-thread cap and WASM overhead, or on an AMD GPU through the existing HIP simulator.
9
-
10
- The browser talks to the native binary over a WebSocket on `127.0.0.1`. By default only `https://drivinglab.jectrum.de` may connect; a CLI argument replaces that list.
11
-
12
- ### Success criteria
13
-
14
- - With `altd-sim serve` running and the setting enabled, a user can create a run with backend "Native CPU" or "Native GPU (HIP)". It trains, saves checkpoints and logs to IndexedDB, and pauses, resumes and changes stages exactly as WASM runs do.
15
- - A native run's checkpoint resumes on WASM and the other way round. The format is shared; results are not bit-identical, see "Known limitation".
16
- - No request reaches the server from an origin that is not allowed, or with a `Host` other than the loopback address and port.
17
- - When the server is missing, unreachable or crashes, the user gets a clear message and the run falls back or resumes as the existing WebGPU and WASM-trap paths do.
18
- - A HIP session matches a native CPU session exactly in car state, as the existing HIP checks require, or falls back to CPU with a reason.
19
-
20
- ### Non-goals
21
-
22
- - The server does not own runs, storage or the stage, plateau and mutation-schedule logic; those stay in the webapp's coordinator worker.
23
- - No remote or LAN access, TLS or authentication tokens.
24
- - No HIP version of the parent-recording turnover (see "Turnover"); that is a later optimization.
25
- - WASM/native bit-exactness is tracked separately in issue #3.
26
-
27
- ## Architecture
28
-
29
- ```
30
- Page (main thread) Coordinator worker altd-sim serve (127.0.0.1)
31
- ├─ setting + status probe ──► (hello only, then close) ──────────► ├─ handshake: Origin + Host check
32
- └─ TrainingWorker ──────────► simulation.worker.ts ├─ one thread per connection
33
- ├─ training loop (unchanged) └─ one Session per connection
34
- ├─ Engine interface ├─ backend: cpu (rayon)
35
- │ ├─ WasmEngine (Simulation, WebGPU) └─ backend: hip (libaltd_gpu.so)
36
- │ └─ RemoteEngine ── WebSocket ──►
37
- └─ IndexedDB (runs, logs, checkpoints)
38
- ```
39
-
40
- The server works as a remote `Simulation`. The worker keeps its training loop and swaps the local `Simulation` for an object that sends the same calls over the socket.
41
-
42
- ## Part 1: HIP backend in `Session` (`driving_sim_rs`)
43
-
44
- ### Native access to Session methods
45
-
46
- Some `Session` items exist only in WASM builds and must also be compiled for the server:
47
-
48
- - `options` field (`src/training/session.rs:76`)
49
- - `set_evolution_settings` (`:313`)
50
- - `replace_track` (`:653`)
51
- - the `network` field the WASM build keeps
52
-
53
- Their cfg changes from "wasm" to "wasm or `server` feature". The server module lives in the library (`src/server/`) so it can use the `pub(crate)` methods directly.
54
-
55
- ### Backend option
56
-
57
- `SessionOptions` gains `backend: "cpu" | "hip"` (camelCase JSON, default `"cpu"`). `deny_unknown_fields` stays.
58
-
59
- - On wasm32, `"hip"` is an error: "the HIP backend is only available in the native simulator".
60
- - On native, `Session` gains `hip: Option<HipState>`:
61
-
62
- ```rust
63
- struct HipState {
64
- world: GpuWorld<'static>,
65
- sim: GpuSim<'static>,
66
- }
67
- static GPU: OnceLock<Result<Gpu, String>> = OnceLock::new(); // Gpu::open(None): ALTD_GPU_LIB or the default path
68
- ```
69
-
70
- The `Gpu` handle is opened once per process and never dropped, so a `Session` can own `'static` GPU handles without self-borrowing.
71
-
72
- ### When HIP is refused
73
-
74
- `Session::new` builds `HipState` only when all of these hold. Otherwise it keeps `hip = None` and records a reason that the server reports, and the session runs on CPU.
75
-
76
- - `GPU` opened successfully.
77
- - The track does not use the native broadphase (`runner.physics` would be `Some`); `advance_window_gpu` rejects it.
78
- - `runner.gpu_sim(...)` succeeds. It already rejects path sensors without `track.curve`.
79
-
80
- Population-dependent capacity is handled on the first window (below), so construction does not need the population.
81
-
82
- ### Routing
83
-
84
- | Session call | CPU | HIP |
85
- |---|---|---|
86
- | `advance(ticks, stop)` | `runner.advance` | `runner.advance_window_gpu(sim, world, ticks, stop, None)` |
87
- | `advance_generation(limit)` | `runner.advance_generation` | `runner.advance_generation_gpu(sim, world, limit)` |
88
- | `next_generation()` | `next_generation_traced` | the same CPU path (see "Turnover") |
89
- | `replace_track(scene)` | as today | as today, then `GpuWorld::new(gpu, &runner.world)` and `sim.set_world(&world)` |
90
- | `start*`, `restore_checkpoint*`, `set_network_json` | as today | as today, then `sim.network_tag = None` |
91
-
92
- Each HIP window reads car and agent state back into `runner.agents`, so `car_states`, `generation_summary`, `network_json`, `metrics`, `active_count` and checkpoints read the runner as they do now.
93
-
94
- If the population is larger than `GpuSim`'s capacity, `GpuSim` is rebuilt with the new population before the window.
95
-
96
- ### Turnover
97
-
98
- `next_generation_gpu` breeds on the GPU but does not produce the parent record (`Lineage`) that format 2 checkpoints store. A HIP session therefore breeds through `next_generation_traced` on the CPU, the same call CPU sessions make. The next window uploads the new networks because `network_tag` no longer matches. Breeding is small next to a generation of driving. A HIP turnover that also records parents can come later if profiling shows it matters.
99
-
100
- ### Startup check
101
-
102
- A HIP session checks itself before its first real window, following `GpuSimulation::verify` in `src/wasm/sim/mod.rs:186-235`:
103
-
104
- 1. Back up `runner.agents`, `tick` and `batch_index`.
105
- 2. Advance 12 ticks on the CPU and record the canonical state (`canonical_state`, moved from `src/wasm/sim` into shared native and WASM code).
106
- 3. Restore the backup, run 12 ticks on HIP, and compare canonical states exactly.
107
- 4. Restore the backup again.
108
-
109
- On a mismatch or HIP error, the session drops `HipState` and continues on CPU with the reason "HIP verification differs from the CPU simulator" (or the error). It runs once per session, on the first `advance` or `advance_generation` after `start*` or `restore*`.
110
-
111
- `Session` exposes `backend() -> "cpu" | "hip"` and `backend_note() -> Option<String>`, so hosts can report what actually runs.
112
-
113
- ### Errors
114
-
115
- HIP failures after the check, such as a failed window, are returned as `Err(String)` and not retried. The webapp fails the run, and resuming continues from the last checkpoint.
116
-
117
- ## Part 2: `altd-sim serve`
118
-
119
- ### Crate layout
120
-
121
- - Feature `server = ["cli", "dep:tungstenite"]`, added to `default`. `tungstenite` is the synchronous WebSocket crate without TLS features, so there is no async runtime.
122
- - `src/server/mod.rs`: listener, handshake checks and the per-connection loop.
123
- - `src/server/protocol.rs`: message types and frame encoding.
124
- - `src/server/dispatch.rs`: operations to `Session` calls.
125
- - `src/bin/altd-sim`: a `Serve` subcommand that parses flags and calls `altd_sim::server::run(config)`.
126
-
127
- ### Flags
128
-
129
- ```
130
- altd-sim [--threads N] serve [--port 47800] [--allow-origin ORIGIN]...
131
- ```
132
-
133
- - `--port`: TCP port, default `47800`. The server binds `127.0.0.1:<port>` only.
134
- - `--allow-origin`: repeatable. When given, the list replaces the default `https://drivinglab.jectrum.de`. Values are normalized as `scheme://host[:port]`, and invalid values are rejected at startup. Local development uses `--allow-origin http://127.0.0.1:5173`.
135
- - `--threads`: the existing global flag; it sizes the rayon pool all CPU sessions share.
136
-
137
- On startup the server prints the address, allowed origins, thread count and HIP availability.
138
-
139
- ### Handshake checks
140
-
141
- `tungstenite::accept_hdr` with a callback that rejects with HTTP 403 and a short plain-text reason unless all hold:
142
-
143
- - The path is `/v1`.
144
- - `Origin` is present and equals an allowed origin exactly (scheme, host and port). `null` is rejected.
145
- - `Host` is `127.0.0.1:<port>` or `localhost:<port>`.
146
-
147
- ### Greeting
148
-
149
- Sent as the first text frame after the handshake:
150
-
151
- ```json
152
- {"type":"hello","protocol":1,"version":"0.1.0","threads":32,
153
- "carStateStride":N,"carStateFields":["..."],
154
- "hip":{"available":true,"device":"..."} | {"available":false,"reason":"..."}}
155
- ```
156
-
157
- Checking HIP availability calls `GPU.get_or_init` once per process. `device` comes from the HIP library if it exposes a name; otherwise it is the library path.
158
-
159
- ### Requests and replies
160
-
161
- - Request (text frame): `{"id":7,"op":"advance","args":{"ticks":180,"stopWhenInactive":true}}`
162
- - Success: `{"id":7,"ok":<result>,"state":State}`
163
- - Failure: `{"id":7,"error":"<text>"}`
164
- - `State` is `{"started","generation","tick","population","activeCount","checkpointGeneration","backend","backendNote"}`.
165
-
166
- Requests are handled strictly in order on the connection's thread. Clients may send the next request before the reply arrives and match replies by `id`.
167
-
168
- ### Binary frames
169
-
170
- Used by `restoreCheckpointBytes` (request), and by `checkpointBytes` and `carStates` (replies):
171
-
172
- ```
173
- [u32 little-endian: JSON length][JSON header][raw payload]
174
- ```
175
-
176
- The JSON header has the same shape as a text frame. `carStates` returns little-endian `f64` values. All other messages are text frames.
177
-
178
- ### Operations
179
-
180
- | op | args | ok |
181
- |---|---|---|
182
- | `create` | `scene`, `network`, `model` (JSON strings), `options` (SessionOptions object, including `backend`) | `{backend, backendNote}` |
183
- | `startWithShape` | `shape: number[]` | `null` |
184
- | `restoreCheckpointBytes` | binary payload | `null` |
185
- | `restoreCheckpointJson` | `json: string` | `null` |
186
- | `advance` | `ticks`, `stopWhenInactive` | executed ticks |
187
- | `advanceGeneration` | `timeLimitTicks` | executed ticks |
188
- | `nextGeneration` | none | `{preservedCount, rewards: number[]}` |
189
- | `setEvolutionSettings` | `json: string` | `null` |
190
- | `replaceTrack` | `scene: string` | `null` |
191
- | `generationSummary` | none | `{bestIndex, bestScore, lapped, active, lapIndex, lapTime}` |
192
- | `networkJson` | `index` | string |
193
- | `carStates` | none | binary `f64` payload |
194
- | `checkpointBytes` | none | binary payload |
195
-
196
- Rules:
197
-
198
- - Any op before `create`, or a second `create`, is an error.
199
- - Only one HIP session may exist per process at a time. A second `create` with `backend: "hip"` falls back to CPU with the note "another session is using the GPU".
200
- - Unknown ops and malformed JSON are errors and leave the session usable. Malformed binary framing closes the connection.
201
- - The session is dropped when the socket closes.
202
-
203
- ### Panics and timeouts
204
-
205
- The release profile keeps `panic = "abort"`, so a panic ends the server. The client sees the socket close (see "Disconnect" below), and a session that panicked part-way would not be trustworthy anyway. There is no per-request timeout, because `advanceGeneration` can take minutes on large populations.
206
-
207
- ## Part 3: webapp client (`driving_webapp_public`)
208
-
209
- ### Setting and status
210
-
211
- - In `#compute-choices` (`src/views.ts` `computeChoices`, wired in `src/main.ts` `bindCompute`), above the backend radios:
212
- - a "Use a local altd-sim" checkbox and a port input;
213
- - help text with the command `altd-sim serve` and the note that the browser may ask once for local network access.
214
- - The setting is stored in `localStorage` (`drivelab.native` = `{enabled, port}`) and is per machine.
215
- - When enabled, the page opens a WebSocket to `ws://127.0.0.1:<port>/v1`, reads `hello`, closes it, and shows one of:
216
- - "Connected: altd-sim 0.1.0 · 32 threads · HIP: <device>"
217
- - "Not reachable on port N"
218
- - "Update altd-sim: protocol N is not supported"
219
-
220
- It probes again when the setting changes and whenever the compute choices are drawn. The page timeout is 3 s.
221
- - New radios:
222
- - "Native CPU · N threads": enabled when connected.
223
- - "Native GPU (HIP) · device": enabled when `hip.available`, otherwise disabled with the server's reason.
224
- - Both carry the note "Results differ slightly from in-browser training", linking to issue #3.
225
- - When the selected native backend becomes unavailable while the user is editing a draft, the draft switches to `"cpu"`, as WebGPU does in `main.ts:115`.
226
-
227
- ### Domain and protocol
228
-
229
- - `Setup.backend` becomes `"cpu" | "webgpu" | "native-cpu" | "native-hip"`.
230
- - `validateSetup` accepts the new values; run summaries and the "Computing on" line show "Native CPU, N threads" and "Native GPU (HIP), <device>".
231
- - `StartCommand` gains `native?: { port: number }`, set by the page from the setting.
232
- - The `engine` event's `backend` gains `"native-cpu" | "native-hip"` and an optional `device`.
233
-
234
- ### Engine interface (`src/engine.ts`)
235
-
236
- ```ts
237
- interface Engine {
238
- readonly started: boolean; readonly generation: number; readonly tick: number;
239
- readonly population: number; readonly activeCount: number;
240
- readonly checkpointGeneration: number | undefined;
241
- startWithShape(shape: Uint32Array): Promise<void>;
242
- restoreCheckpointBytes(bytes: Uint8Array): Promise<void>;
243
- restoreCheckpointJson(json: string): Promise<void>;
244
- advance(ticks: number, stopWhenInactive: boolean): Promise<number>;
245
- advanceGeneration(timeLimitTicks: number): Promise<number>;
246
- nextGeneration(): Promise<void>;
247
- setEvolutionSettings(json: string): Promise<void>;
248
- replaceTrack(sceneJson: string): Promise<void>;
249
- generationSummary(): Promise<Summary>;
250
- networkJson(index: number): Promise<string>;
251
- carStates(): Promise<Float64Array>;
252
- checkpointBytes(): Promise<Uint8Array>;
253
- free(): void;
254
- }
255
- ```
256
-
257
- - `WasmEngine` wraps `lib.Simulation` and holds the existing WebGPU logic (`prepareGpu`, `dropGpu`, the GPU-to-CPU fallback in `advance`).
258
- - `RemoteEngine` opens the socket, checks `hello.protocol === 1`, sends `create`, and updates the cached getters from every reply's `state`. Its getters are synchronous because they return those cached values.
259
- - `simulation.worker.ts` replaces `sim` and `gpu` with one `engine: Engine` and adds `await` to the calls that become asynchronous. The training loop, storage queue, stage logic and messages are otherwise unchanged.
260
- - The WASM library still loads for every backend, because `trackScene` and `randomTrackScene` run in the worker.
261
-
262
- ### Fallback and disconnect
263
-
264
- - **Server unreachable at `buildSession`, `hello` rejected, or `create` failing:** the run uses `WasmEngine` on CPU and emits an `engine` event with a note, for example "The local altd-sim could not be reached on port 47800, so this run trains in the browser. <reason>".
265
- - **HIP refused or failing its check:** the server reports `backend: "cpu"` with `backendNote`, and the worker emits `engine` `native-cpu` with that note.
266
- - **Disconnect during a run:** `RemoteEngine` rejects all pending and future calls with "The native simulator closed the connection. Resuming continues from the last saved checkpoint." The worker treats this like a WASM trap: it sets `trapped`, so `publishRun(true)` skips `checkpointBytes`, marks the run failed, stores it, and reports the error. Resuming goes through the same start path, including the fallback above.
267
-
268
- ### Content Security Policy
269
-
270
- Add `ws://127.0.0.1:*` to `connect-src` in `public/_headers` and in `vite.config.ts`. `deploy/deploy.sh` reads `_headers`, and `scripts/serve-test.mjs` reads the same policy. COOP/COEP do not apply to WebSocket connections.
271
-
272
- ## Known limitation
273
-
274
- WASM and native CPU are not bit-exact (issue #3). Native CPU and HIP are expected to be exact with each other, and the startup check enforces it. Cross-engine resume works through the shared checkpoint format, but continued training diverges. The UI says so next to the native choices.
275
-
276
- ## Testing
277
-
278
- ### `driving_sim_rs`
279
-
280
- - **Unit:**
281
- - origin normalization and matching: exact, different port, different scheme, trailing slash, `null`, missing;
282
- - Host matching;
283
- - binary frame encode and decode, including truncated frames;
284
- - `SessionOptions` with `backend` (`"hip"` rejected on wasm by a cfg test).
285
- - **Integration (`tests/server.rs`):** start the server in-process on port 0 and connect with a `tungstenite` client.
286
- - A disallowed origin and a wrong Host get 403.
287
- - `hello` contents.
288
- - `create → startWithShape → advance → advanceGeneration → nextGeneration → generationSummary → carStates → checkpointBytes → restoreCheckpointBytes` matches a direct `Session` with the same inputs bit for bit.
289
- - Ops before `create` and a second `create` return errors.
290
- - A dropped socket frees the session.
291
- - **HIP (skipped when `Gpu::open` fails):**
292
- - a CPU and a HIP `Session` agree in canonical state through several `advance` windows, `advanceGeneration` and two turnovers;
293
- - a checkpoint saved under HIP restores under CPU, and the other way round;
294
- - fallback reasons for native broadphase and a missing curve;
295
- - a second concurrent HIP session falls back to CPU.
296
- - Existing tests: `cargo test`, the WASM parity harness, and a WASM build that confirms the cfg changes do not leak native-only code.
297
-
298
- ### `driving_webapp_public`
299
-
300
- - Domain tests: `validateSetup` with the new backends.
301
- - Playwright (`tests/native.spec.ts`): build `altd-sim` from `SIM_ROOT` and start `altd-sim serve --port <free> --allow-origin http://127.0.0.1:<test port>`.
302
- - The setting shows "Connected".
303
- - A two-generation Native CPU run stores progress and a checkpoint, with the correct engine event.
304
- - Setting enabled with no server: the run falls back to CPU with a note.
305
- - Killing the server mid-run fails the run with the disconnect message; restarting the server and resuming continues from the checkpoint.
306
- - CSP permits the socket.
307
- - The HIP case is skipped unless the server reports HIP available.
308
-
309
- ## Documentation
310
-
311
- - `docs/server.md`: purpose, flags, security model, the protocol (greeting, ops, frames) and fallback behavior.
312
- - `docs/cli.md`: the `serve` subcommand.
313
- - `docs/gpu.md`: HIP through `Session`, and CPU turnover with network re-upload.
314
- - Webapp `README.md`: the setting, the CSP change and native testing.
315
-
316
- ## Delivery order
317
-
318
- 1. HIP backend in `Session`, with its tests. Independently useful; no server needed.
319
- 2. `altd-sim serve` and the protocol, with integration tests (CPU, then HIP).
320
- 3. Webapp client, CSP and Playwright tests.
321
-
322
- Each phase lands with green tests before the next starts.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
github-simulator/source/docs/wasm.md DELETED
@@ -1,27 +0,0 @@
1
- # WASM and WebGPU fidelity notes
2
-
3
- The serial and threaded packages compile the same Session and TrainingRunner code. The threaded package rebuilds Rust's standard library with atomics and uses `wasm-bindgen-rayon`; it requires an initialized worker pool before constructing worlds or invoking Rayon. Both packages preserve the existing arithmetic and RNG algorithms.
4
-
5
- Three comparisons answer different questions:
6
-
7
- - Native versus WASM state/reference checks catch portability differences in the exported fields.
8
- - Serial versus threaded WASM checks cover states, sensors, controls, metrics, rewards, summaries and binary checkpoints, including exchange between the two packages.
9
- - WebGPU versus WASM checks validate query or full-window device results against the WASM CPU implementation.
10
-
11
- Expanded native parity is incomplete. On the public generated Formula scenario, serial and threaded WASM matched each other in 253,341 values per mode, including the optional score aggregates, but both differed from native in 2,285 values per mode. Those differences comprised 703 controls, 405 metrics and 1,177 checkpoint bytes. The original captured-scene baseline had 2,532 native differences with the same exact serial/threaded equality. Counts depend on the scenario, build and checkpoint representation. `STRICT_NATIVE=1` makes the browser test fail on any expanded native difference.
12
-
13
- ## Device arithmetic
14
-
15
- The WebGPU raycaster keeps simulation on the CPU and casts rays or nearest-wall queries on-device. Explicit float32 rounding boundaries prevent fusion and reassociation. Division corrects a hardware estimate using an exact integer remainder, with an integer-loop fallback; square root and software binary64 division use the same principle. Full `GpuSimulation` also implements binary64 arithmetic in integer WGSL operations and keeps network accumulation ordered.
16
-
17
- Historical RX 7900 XTX checks with RADV 26.2.2 matched 65,536 rays and 65,536 nearest-wall points per scenario, and millions of in-simulation rays across Formula and three Rally scenes. A newer baseline repeated a smaller 4,000-query corpus and 119,743 in-simulation rays with zero differences. The public replacements contain four distinct generated tracks and native current-code references, not game-oracle captures.
18
-
19
- WGSL permits device-dependent subnormal and NaN behavior. Raw division fixtures check signed zero, subnormal boundaries, infinities and broad exponent coverage; NaN payloads are treated as equivalent in that arithmetic diagnostic. Simulation comparisons retain exact values and count differences without substituting CPU results. Results on one GPU do not validate every browser adapter.
20
-
21
- ## Runtime and memory
22
-
23
- Threaded WASM uses imported shared memory and a 2 GiB growth ceiling. This is a maximum, not an initial allocation. Workers need stack and TLS memory; an application's separately loaded preview module has its own memory. Shared-memory packages require cross-origin isolation and complete generated helper snippets.
24
-
25
- A host must await GPU windows before mutating the Session. A failed full-GPU window keeps the last committed WASM state so it can continue on CPU. Paused physics and native shared broadphase are unsupported by full WebGPU. The raycaster has one readback per tick; full simulation batches bounded windows, which changes the population size at which device work can pay off.
26
-
27
- [The WASM guide](../wasm/README.md) contains build commands, initialization and the browser harness. [Performance notes](performance.md) distinguish CPU worker scaling, startup and WebGPU measurements.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
github-simulator/source/gpu/README.md DELETED
@@ -1,105 +0,0 @@
1
- # GPU backends (AMD HIP, NVIDIA CUDA)
2
-
3
- The GPU library runs whole driving generations on an AMD GPU (HIP) or an NVIDIA GPU (CUDA, see below). Captured CPU/HIP checks compare simulation values, population parameters, RNG state and checkpoint bytes exactly. Rust owns evolution and checkpoint I/O; both backends can resume the same generation-boundary checkpoints. See [fidelity](../docs/fidelity.md) for the scope of that evidence.
4
-
5
- ## Build and use
6
-
7
- Linux release archives include `libaltd_gpu.so` beside `altd-sim`, built with ROCm 7.1 for the targets in `release-targets`. They need a ROCm 7.x runtime that provides `libamdhip64.so.7`, but no compiler. `altd-sim gpu-info` reports the loaded library. To build the library yourself, install ROCm with `hipcc`, then build from the repository root:
8
-
9
- ```sh
10
- gpu/build.sh
11
- cargo build --release --offline
12
-
13
- target/release/altd-sim --threads 8 train-scratch --gpu \
14
- --scene assets/scenes/rally_template.json --track-mode random \
15
- --random-track-settings assets/random_track_settings.json \
16
- --population 256 --generations 3 --ticks 600 --seed 1729 \
17
- --eliminate-on-wall --idle-eliminate --out-dir runs/gpu-example
18
- ```
19
-
20
- `OUT` overrides the library output directory, default `target/gpu`. `GPU_ARCH` lists one or more architectures separated by commas or spaces, default `gfx1100` for RX 7900 XTX; `rocminfo` reports a GPU's name. `GPU_ARCH="$(cat gpu/release-targets)"` builds the release library for every consumer target.
21
-
22
- `--gpu` and `gpu-info` load `ALTD_GPU_LIB` when set. Otherwise they try `libaltd_gpu.so` beside the executable, then `target/gpu` of the checkout that built the binary. Load errors list each attempted path.
23
-
24
- | Targets | GPUs |
25
- | --- | --- |
26
- | gfx803, gfx900, gfx902, gfx906, gfx909, gfx90c | Polaris and Vega: RX 470-590, Vega 56/64, Radeon VII, Vega APUs |
27
- | gfx1010-gfx1013 | RDNA1: RX 5500-5700 XT |
28
- | gfx1030-gfx1036 | RDNA2: RX 6400-6950 XT, Steam Deck, Radeon 610M/680M |
29
- | gfx1100-gfx1103, gfx1150-gfx1153 | RDNA3 and RDNA3.5: RX 7600-7900 XTX, Radeon 780M/890M, Strix Halo |
30
- | gfx1200, gfx1201 | RDNA4: RX 9060/9070 |
31
-
32
- The ROCm 7.1 runtime officially supports fewer consumer GPUs than this list; the remaining targets are best effort. The captured CPU/HIP equivalence checks have run on gfx1100 only. The script verifies the checked-in double tables against their Rust bit patterns without rewriting tracked files. `python3 gpu/gen_tables.py --output PATH` writes a header explicitly; `--check` validates it.
33
-
34
- The compiler flags `-ffp-contract=off` and `-fhip-fp32-correctly-rounded-divide-sqrt` preserve separate multiply/add rounding and correctly rounded float32 division/square root. Explicit `fma` calls in Windows kernels still fuse and round once. Keep these flags when changing architecture. The native crate loads the library at runtime, so CPU-only builds do not require ROCm.
35
-
36
- ## Math profiles
37
-
38
- Each library contains `proton`, `win10-fma3` and `win11-fma3`; a build selects GPU architectures, while each simulation selects its math profile. `--math-profile win11-fma3` works with `--gpu` on Linux, for example. Without that flag the CLI detects its host profile; resumed scratch runs retain the saved profile. Server sessions use `options.mathProfile`, defaulting to the server's profile. [Math profiles](../math/README.md) documents the shared Windows kernels and the existing musl implementations.
39
-
40
- ## NVIDIA (CUDA)
41
-
42
- The same sources build for NVIDIA GPUs with `nvcc`; `sim/compat.h` maps the HIP runtime calls and warp helpers to CUDA. HIP and CUDA use the same library ABI and checkpoint formats: `--gpu`, `gpu-info` and `backend: "hip"` use whichever library is loaded. Math profiles require simulator ABI 10, so rebuild older libraries. Install the CUDA toolkit (13.x tested) and a host compiler (Visual Studio Build Tools on Windows, gcc or clang on Linux), then build from the repository root:
43
-
44
- ```sh
45
- gpu/build-cuda.sh # Linux, writes target/gpu/libaltd_gpu.so
46
- gpu/build-cuda.ps1 # Windows, writes target/gpu/altd_gpu.dll
47
- ```
48
-
49
- `OUT` overrides the output directory. `CUDA_ARCH` defaults to `native`, which builds for the GPUs of the build machine. Without a GPU, nvcc 13.4 warns and builds `sm_75` code and PTX instead, which newer GPUs compile at load time. To build for other GPUs, or several, list `sm_` targets separated by commas or spaces; `nvidia-smi --query-gpu=compute_cap --format=csv` reports the number, so 8.6 is `sm_86`. A list also embeds PTX for its newest target, which the driver compiles at load time for a newer GPU. CUDA 13 builds for Turing (`sm_75`, RTX 20 series) and newer only; older GPUs need a CUDA 12 toolkit, which is untested. Both scripts check the double tables with `gpu/gen_tables.py --check` (`python3` on Linux, the `py` launcher or `python` on Windows). The binary loads `ALTD_GPU_LIB`, then the library beside the executable, then `target/gpu`, as on AMD. `altd-sim gpu-info` runs one kernel when a GPU is present, so a library built for another GPU fails there with HIP error 209.
50
-
51
- nvcc rejects a Visual Studio newer than the toolkit supports. `gpu/build-cuda.ps1 -AllowUnsupportedCompiler` (or `CUDA_ALLOW_UNSUPPORTED_COMPILER=1`) builds anyway with a warning; NVIDIA has not validated that combination, so run the checks below before trusting the library.
52
-
53
- `-fmad=false` is the CUDA counterpart of `-ffp-contract=off`; keep it, and keep nvcc's default correctly rounded float32 division and square root (no `-use_fast_math`, no `-ftz=true`). NVIDIA arithmetic also replaces every NaN result with its canonical NaN, so the places where the CPU returns a NaN operand or the x86 default NaN call `altd_nan_operand` and `altd_invalid` from `sim/compat.h`, which build those bits explicitly on both vendors.
54
-
55
- All three math profiles passed primitive and simulation checks on an RTX 3060 Ti (sm_86, Linux, CUDA 13.0); see the [verification report](../math/verification.md). Earlier Proton baseline checks passed on an RTX 4070 Laptop (sm_89, Windows, CUDA 13.4), and on Linux on an RTX 2070 (sm_75, driver 580) and an RTX 3060 (sm_86, driver 595) with `build-cuda.sh` libraries from CUDA 13.4: `native`, and `sm_75,sm_86`. They also passed with a CUDA 13.0 `sm_75` library run through its PTX (`CUDA_FORCE_PTX_JIT=1`). On those three GPUs the baseline `train-scratch --gpu` checkpoints were byte-identical to the CPU's. The driver compiles PTX only from a toolkit no newer than itself, so PTX for newer GPUs needs a driver at least as new as the CUDA toolkit that built the library. Consumer NVIDIA GPUs run float64 at 1/64 of their float32 rate, which bounds the network forward pass. A Windows GPU that drives a display kills kernels that run for more than a couple of seconds; the windowed launches stay well below that in the checks above.
56
-
57
- ## Execution model
58
-
59
- GPU driving uses tick-major execution for independent cars. Native shared broadphase and paused windows are unsupported. Generated CLI tracks disable shared broadphase. Track preparation runs on a CPU producer with a bounded queue; `--track-buffer-size` sets its depth, default eight. Population/network buffers stay allocated while each fresh track replaces geometry.
60
-
61
- ## Validation and measurements
62
-
63
- ```sh
64
- cargo build --release --offline --example gpu_check
65
- target/release/examples/gpu_check --help
66
- target/release/examples/gpu_check schedules
67
- ```
68
-
69
- The default check fixture is a fixed generated Rally track and seeded Xavier networks. `ALTD_GPU_SCENE`, `ALTD_GPU_SPAWN`, `ALTD_GPU_NETWORK`, `ALTD_GPU_MODEL` and `ALTD_GPU_CKPT` select explicit inputs or a saved population. No captured campaign scene is required. `gpu_check --help` lists primitive, query, sensing, inference, physics and generation checks. Exhaustive parts can take minutes.
70
-
71
- `gpu_check math` compares primitives under all three profiles with the CPU. `ALTD_GPU_MATH` selects the simulation fixture's profile, default `proton`. Run complete simulation checks for each profile on the library's actual GPU:
72
-
73
- ```sh
74
- for profile in proton win10-fma3 win11-fma3; do
75
- ALTD_GPU_MATH="$profile" ALTD_GPU_LIB=target/gpu/libaltd_gpu.so \
76
- target/release/examples/gpu_check \
77
- rays sensors infer step stats window schedules reuse novelty turnover
78
- done
79
- ```
80
-
81
- Run benchmarks on an otherwise idle GPU:
82
-
83
- ```sh
84
- RAYON_NUM_THREADS=8 python3 gpu/benchmark.py \
85
- --library target/gpu/libaltd_gpu.so --cars 8192 32768 \
86
- --samples 5 --warmups 1 --no-elimination --output target/gpu-fixed.json
87
- RAYON_NUM_THREADS=8 python3 gpu/benchmark.py --training \
88
- --library target/gpu/libaltd_gpu.so --cars 8192 --samples 5 \
89
- --output target/gpu-training.json
90
- ```
91
-
92
- The runner keeps every sample and validates result digests. `--checkpoint DIR` selects a saved population; omitting it uses the fixed Xavier recipe. `--scene`, `--spawn-trace`, `--network`, `--model` and `--binary` override inputs. Fixed-window timing excludes fixture construction, reset, hashing and reproduction; training timing includes consecutive generation turnover. Elimination can finish early, so inspect executed ticks before comparing results.
93
-
94
- `gpu/profile.sh` collects phase timings, optional rocprofv3 traces/counters and diagnostic kernel builds. `--only 1,2`, `--sizes "8192 32768"`, `--checkpoint DIR` and `--output target/profile` select the work. Profiling changes execution behavior; final timing should run with profiling disabled. [Performance notes](../docs/performance.md) retain measured hardware results.
95
-
96
- | Variable | Effect |
97
- | --- | --- |
98
- | `ALTD_GPU_LIB` | Runtime shared-library path |
99
- | `ALTD_GPU_MATH` | Math profile of `gpu_check` simulation fixtures |
100
- | `ALTD_GPU_GRAPH=0` | Direct launches instead of HIP graph replay |
101
- | `ALTD_GPU_SPLIT=0` | Fused instead of split physics |
102
- | `ALTD_GPU_PROFILE=1` | Device phase timings; `host` reports host/wall time only |
103
- | `ALTD_TRAIN_PROFILE=1` | CPU reproduction, installation and transfer timings |
104
-
105
- [Implementation notes](../docs/gpu.md) explain batching, graph lifetime, exact reduction order and memory costs. `gpu_engine_scan` is an exhaustive native/GPU trigonometry developer tool; it requires an explicit thread count and output header, and is not part of the regular test suite.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
github-simulator/source/gpu/benchmark.py DELETED
@@ -1,117 +0,0 @@
1
- #!/usr/bin/env python3
2
- """Benchmark identical GPU generations; build examples/gpu_check first."""
3
- import argparse
4
- import hashlib
5
- import json
6
- import os
7
- from pathlib import Path
8
- import statistics
9
- import subprocess
10
-
11
-
12
- def main():
13
- parser = argparse.ArgumentParser(description=__doc__)
14
- parser.add_argument("--library", type=Path, required=True)
15
- parser.add_argument("--cars", type=int, nargs="+", default=[8192, 32768, 262144])
16
- parser.add_argument("--ticks", type=int, default=5400)
17
- parser.add_argument("--samples", type=int, default=3)
18
- parser.add_argument("--warmups", type=int, default=1)
19
- parser.add_argument("--no-elimination", action="store_true")
20
- parser.add_argument("--training", action="store_true", help="include turnover across consecutive generations")
21
- parser.add_argument("--generations", type=int, default=3)
22
- parser.add_argument("--binary", type=Path, help="gpu_check executable (also supports saved baselines)")
23
- parser.add_argument("--checkpoint", type=Path, help="saved train-scratch population; otherwise use the fixed generated fixture")
24
- parser.add_argument("--scene", type=Path, help="explicit scene instead of the generated track")
25
- parser.add_argument("--spawn-trace", type=Path, help="spawn trace for an explicit scene")
26
- parser.add_argument("--network", type=Path, help="sensor/control names")
27
- parser.add_argument("--model", type=Path, help="vehicle sensor model")
28
- parser.add_argument("--output", type=Path, required=True)
29
- args = parser.parse_args()
30
- for key, variable in [("checkpoint", "ALTD_GPU_CKPT"), ("scene", "ALTD_GPU_SCENE"),
31
- ("spawn_trace", "ALTD_GPU_SPAWN"), ("network", "ALTD_GPU_NETWORK"),
32
- ("model", "ALTD_GPU_MODEL")]:
33
- value = getattr(args, key)
34
- if value is not None:
35
- os.environ[variable] = str(value.resolve())
36
- root = Path(__file__).resolve().parent.parent
37
- library = args.library.resolve()
38
- binary = args.binary.resolve() if args.binary else root / "target/release/examples/gpu_check"
39
- if args.samples < 1 or args.warmups < 0 or args.generations < 1:
40
- parser.error("samples and generations must be positive; warmups must be nonnegative")
41
- if args.training and args.no_elimination:
42
- parser.error("the training benchmark uses the fixture's elimination settings")
43
- report = {
44
- "benchmark": "training" if args.training else "fixed_generation",
45
- "binary": str(binary),
46
- "binary_sha256": hashlib.sha256(binary.read_bytes()).hexdigest(),
47
- "library": str(library),
48
- "library_sha256": hashlib.sha256(library.read_bytes()).hexdigest(),
49
- "requested_ticks": args.ticks,
50
- "rayon_threads": os.environ.get("RAYON_NUM_THREADS", "default"),
51
- "graph": os.environ.get("ALTD_GPU_GRAPH", "default"),
52
- "split": os.environ.get("ALTD_GPU_SPLIT", "default"),
53
- "profile": os.environ.get("ALTD_GPU_PROFILE", "off"),
54
- "training_profile": os.environ.get("ALTD_TRAIN_PROFILE", "off"),
55
- "generations": args.generations if args.training else 1,
56
- "samples": args.samples,
57
- "warmups": args.warmups,
58
- "eliminate": not args.no_elimination,
59
- "results": [],
60
- }
61
- report["fixture_inputs"] = {key: os.environ[key] for key in [
62
- "ALTD_GPU_CKPT", "ALTD_GPU_SCENE", "ALTD_GPU_SPAWN", "ALTD_GPU_NETWORK", "ALTD_GPU_MODEL"
63
- ] if key in os.environ}
64
- if "ALTD_GPU_CKPT" in os.environ:
65
- checkpoint = Path(os.environ["ALTD_GPU_CKPT"])
66
- metadata = json.loads((checkpoint / "checkpoint.json").read_text())
67
- report["checkpoint_sha256"] = hashlib.sha256((checkpoint / metadata["population_file"]).read_bytes()).hexdigest()
68
- else:
69
- report["population_recipe"] = {"initialization": "Xavier", "seed": 1, "shape": [20,16,16,16,16,12,12,8,5]}
70
- for cars in args.cars:
71
- env = dict(os.environ, ALTD_GPU_LIB=str(library), ALTD_GPU_BENCH_CARS=str(cars),
72
- ALTD_GPU_BENCH_TICKS=str(args.ticks), ALTD_GPU_BENCH_SAMPLES=str(args.samples),
73
- ALTD_GPU_BENCH_WARMUPS=str(args.warmups),
74
- ALTD_GPU_BENCH_GENERATIONS=str(args.generations),
75
- ALTD_GPU_BENCH_ELIMINATE=str(int(not args.no_elimination)))
76
- command = [str(binary), "benchtrain" if args.training else "benchfixed"]
77
- records = []
78
- for sample in range(args.warmups + args.samples if args.training else 1):
79
- trial = []
80
- with subprocess.Popen(command, cwd=root, env=env, stdout=subprocess.PIPE, text=True) as process:
81
- for line in process.stdout:
82
- print(line, end="", flush=True)
83
- if line.startswith("{"):
84
- record = json.loads(line)
85
- if args.training:
86
- record.update(sample=sample, warmup=sample < args.warmups)
87
- trial.append(record)
88
- if process.wait():
89
- raise SystemExit(f"benchmark failed for {cars} cars")
90
- if args.training and [r["generation"] for r in trial] != list(range(args.generations)):
91
- raise SystemExit("missing training generations")
92
- records.extend(trial)
93
- if args.training:
94
- generations = []
95
- for generation in range(args.generations):
96
- runs = [r for r in records if r["generation"] == generation]
97
- timed = [r for r in runs if not r["warmup"]]
98
- if len(timed) != args.samples or len({r["digest"] for r in runs}) != 1:
99
- raise SystemExit("missing samples or inconsistent training results")
100
- generations.append({"generation": generation, "digest": runs[0]["digest"], **{
101
- "median_" + key: statistics.median(r[key] for r in timed)
102
- for key in ["simulate_seconds", "turnover_seconds", "total_seconds"]}})
103
- timed = [sum(r["total_seconds"] for r in records if r["sample"] == sample) / args.generations
104
- for sample in range(args.warmups, args.warmups + args.samples)]
105
- result = {"cars": cars, "median_seconds": statistics.median(timed), "generations": generations, "runs": records}
106
- else:
107
- timed = [r["seconds"] for r in records if not r["warmup"]]
108
- if len(timed) != args.samples or len({r["digest"] for r in records}) != 1:
109
- raise SystemExit("missing samples or inconsistent results")
110
- result = {"cars": cars, "median_seconds": statistics.median(timed), "runs": records}
111
- report["results"].append(result)
112
- args.output.parent.mkdir(parents=True, exist_ok=True)
113
- args.output.write_text(json.dumps(report, indent=2) + "\n")
114
-
115
-
116
- if __name__ == "__main__":
117
- main()