TiGa-RCE commited on
Commit
76e0bfa
·
verified ·
1 Parent(s): b4691b7

Add 28 accurately labeled built-in replica tracks and synchronized selectors

Browse files
Files changed (40) hide show
  1. DATA_POLICY.md +10 -0
  2. FRONTEND_SOURCE.json +1 -1
  3. README.md +1 -1
  4. RELEASE_MANIFEST.json +39 -7
  5. STORAGE_BOUNDARY.md +2 -0
  6. TRACK_LIBRARY.md +37 -0
  7. builtin_tracks.py +55 -0
  8. builtin_tracks/catalog.json +494 -0
  9. builtin_tracks/tracks/Replica A01 Beginner.track +0 -0
  10. builtin_tracks/tracks/Replica A02 Sharp Turns.track +0 -0
  11. builtin_tracks/tracks/Replica A03 High Speed.track +0 -0
  12. builtin_tracks/tracks/Replica A04 Dirt.track +0 -0
  13. builtin_tracks/tracks/Replica A05 Two Terrains.track +0 -0
  14. builtin_tracks/tracks/Replica A06 Ice.track +0 -0
  15. builtin_tracks/tracks/Replica A07 Three Terrains.track +0 -0
  16. builtin_tracks/tracks/Replica A08 Long.track +0 -0
  17. builtin_tracks/tracks/Replica A09 Sharpest.track +0 -0
  18. builtin_tracks/tracks/Replica B01 Oval.track +0 -0
  19. builtin_tracks/tracks/Replica B02 Snake.track +0 -0
  20. builtin_tracks/tracks/Replica B03 Slalom.track +0 -0
  21. builtin_tracks/tracks/Replica B04 Rally.track +0 -0
  22. builtin_tracks/tracks/Replica B05 Racetrack.track +0 -0
  23. builtin_tracks/tracks/Replica B06 Hard.track +0 -0
  24. builtin_tracks/tracks/Replica B07 Drift.track +0 -0
  25. builtin_tracks/tracks/Replica B08 Arctic Circle.track +0 -0
  26. builtin_tracks/tracks/Replica B09 Checkered.track +0 -0
  27. builtin_tracks/tracks/Replica R01 Blitzring.track +0 -0
  28. builtin_tracks/tracks/Replica R02 Desert Rally.track +0 -0
  29. builtin_tracks/tracks/Replica R03 Glacier.track +0 -0
  30. builtin_tracks/tracks/Replica R04 Truck Maze.track +0 -0
  31. builtin_tracks/tracks/Replica R05 Endurance 500.track +0 -0
  32. builtin_tracks/tracks/Replica R06 Mix.track +0 -0
  33. builtin_tracks/tracks/Replica R07 Mirage Marina.track +0 -0
  34. builtin_tracks/tracks/Replica R08 Demolition Derby.track +0 -0
  35. builtin_tracks/tracks/Replica R09 Eau Noir.track +0 -0
  36. builtin_tracks/tracks/Replica The Champions Trial.track +0 -0
  37. client.js +9 -3
  38. index.html +83 -1
  39. server.py +14 -1
  40. track-library.js +79 -0
DATA_POLICY.md CHANGED
@@ -7,6 +7,16 @@ training, analytics or public examples. Inputs remain in the browser until Run.
7
  The interface supports native CPU and, on a ZeroGPU deployment, an explicitly
8
  selected GPU job. CPU requests do not acquire a GPU lease.
9
 
 
 
 
 
 
 
 
 
 
 
10
  GPU inputs await dispatch in application memory for at most 120 seconds. The
11
  queue receives a random one-use ticket, not the uploaded track or network bytes.
12
  Inputs are released from the pending store on dispatch, expiry or shutdown.
 
7
  The interface supports native CPU and, on a ZeroGPU deployment, an explicitly
8
  selected GPU job. CPU requests do not acquire a GPU lease.
9
 
10
+ The built-in replica track library is a separate, intentionally reusable public
11
+ reference collection shipped with the app. Visitors can retrieve these listed,
12
+ hash-checked files. They are programmatically reconstructed editor-format
13
+ replicas, not editor-authored or official packaged track files. Job deletion does
14
+ not erase this reference library; it erases only submitted job copies and job
15
+ results under the rules below. Custom uploaded tracks/networks are never added
16
+ to the library. Track selection and reference bytes may remain in this page's
17
+ memory across runs, but are not saved in cookies, localStorage or recipes.
18
+ See TRACK_LIBRARY.md in the release package for provenance and limitations.
19
+
20
  GPU inputs await dispatch in application memory for at most 120 seconds. The
21
  queue receives a random one-use ticket, not the uploaded track or network bytes.
22
  Inputs are released from the pending store on dispatch, expiry or shutdown.
FRONTEND_SOURCE.json CHANGED
@@ -4,5 +4,5 @@
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": "9e5b6bd69dd587f0e5c0f551b291de4d6a729e601916042cde0449ba2162bee8"
8
  }
 
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": "11237dcf43bb2744cbb83982e44fa4db35da81c24d5c0df48d896f8973bac0b5"
8
  }
README.md CHANGED
@@ -11,7 +11,7 @@ hf_oauth_expiration_minutes: 60
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. No bundled tracks or networks.
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
 
 
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
 
RELEASE_MANIFEST.json CHANGED
@@ -2,27 +2,59 @@
2
  "backend": "cpu+zerogpu",
3
  "files": {
4
  "BETA_TESTING.md": "d511965b9d675a092571f8815348da991ef1ef6be3766266c1f98ff393fd3a4d",
5
- "DATA_POLICY.md": "8a954c46d39783582b2d4fbaa0fa2510e2e13446b0dff0b3c66f8817341b0289",
6
- "FRONTEND_SOURCE.json": "1e31b153757fd42c3bc2abaa1982a44e19a2ed7dc259d32781f36bb9a3ee10b7",
7
  "GODOT_LICENSE": "fb2b3bb82c60f1e76841ba2122eb902f8e39c151476fe21ce10c9a05d1045304",
8
  "IMPORTER_BUILD_RECEIPT.json": "4ba5c533cc617105478e4d85c83f456a7dfa68b1388049624619871ba9e42e9d",
9
  "LICENSE": "53d5851b6440feeae36f72a5f57fcab37858c48b7084765ece4b0c54b9a28ed8",
10
- "README.md": "11abed635d4192b5ea8d8891fc38e3a60989ad5b4696683d0321f3bc12eba20f",
11
- "STORAGE_BOUNDARY.md": "85442bbaffdf1208a1b7d3359cf1f0a2000a2d1ca46594b3a5fe23d52db41e00",
 
12
  "app.py": "704f789a41846b0a5bc1d3f6f5305d7ac5a6b1719ff77c23585b89fd3e68d55d",
13
  "app_release.py": "7482559c667a665fd3cb6aa8af6c78422a822b515e14589db8306f7fd4860a8b",
14
  "assets/formula_template.json": "80f745df82bb7be45af52785fd582460bcddc63c5a4e1d8375d85b3122db4c6b",
15
  "bin/altd-sim": "2f2f2144ae14b0ef599ca8510f95712da00243c6875881491d384b394e7499f7",
16
  "bin/extract_saved_track": "3a7733c45b4301a786fcbfe92660a1c484749272da5f608d62f34878bd4ff31a",
17
  "bin/libaltd_gpu.so": "279d6353b4c691686d6aeeae6abfd4a82b959e9b604f079a6c45f9823b48a87a",
18
- "client.js": "79a34470942132a4e4a4100ae92b805ff02f7fe344e7962cfcff6a1208cef54a",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  "delivery.py": "4f5a4e45df92e5cbfdef6eb449ede9ba26217fe24da376fafddae5cbbb73847a",
20
  "gpu_tickets.py": "c32cb5de751d49d3e1cd970c7d6328a42ebe71602dd9fd3788c872eef42611da",
21
  "hf-auth.js": "743fa2b62c611fcc6064664691e133efb5d163412955b2a9d0a562a428412864",
22
  "hf_identity.py": "6993d0238ada835606dbdc3275c17a3fe5a5cac5ad2156ab78230acf2d051eba",
23
- "index.html": "9e5b6bd69dd587f0e5c0f551b291de4d6a729e601916042cde0449ba2162bee8",
24
  "requirements.txt": "9b532747e51bd052e82090ece860d6dafe027407f4512dc74272c148ea104c22",
25
- "server.py": "dda63ffe8e9ea0191c940fcb996ed790cbb21b8be96e83aeca2a67c33ce45582",
 
26
  "training_config.py": "2b9768876fdc60b16afb45b98023c6c31666e30f7c56f1292f6071775e6da0c5",
27
  "vendor/gradio-client/LICENSE": "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4",
28
  "vendor/gradio-client/dist/index.min.js": "fdd776db8633354f118fe2908c980592283968737e6b91dc3aa86d648da5c3fd",
 
2
  "backend": "cpu+zerogpu",
3
  "files": {
4
  "BETA_TESTING.md": "d511965b9d675a092571f8815348da991ef1ef6be3766266c1f98ff393fd3a4d",
5
+ "DATA_POLICY.md": "1434ac5420a611b35c69da90bbbb70abb088754fdab0354a51f0f892b4abe224",
6
+ "FRONTEND_SOURCE.json": "e49a81a9ea37fb6724eaeac9630af249b721b983ed38e1f395d6c4db6fda0834",
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",
22
+ "builtin_tracks/tracks/Replica A02 Sharp Turns.track": "097f1ea8edf041112b690d0638075630716ddc03c7d0b1980ddcbeaf5071c8d4",
23
+ "builtin_tracks/tracks/Replica A03 High Speed.track": "88917c63847be1854b989bb28a23af7eeacb964c3e7df9579953aebc9496e6af",
24
+ "builtin_tracks/tracks/Replica A04 Dirt.track": "7f4fe58516227b15898d14bb0abb9a0856126d24fcd793884f051f7a4fae521d",
25
+ "builtin_tracks/tracks/Replica A05 Two Terrains.track": "c4ee2842920d99cdfe3eebdcad59a77e24b626380acef0d02a39ea1e23823e2a",
26
+ "builtin_tracks/tracks/Replica A06 Ice.track": "fccb9a159a06d1b986c6fe7d5bb89c0cabad3a005531f4e0d71f6e37254ada34",
27
+ "builtin_tracks/tracks/Replica A07 Three Terrains.track": "a8fa652ad451e2702a23d5f3429eb0b6a6408bf6a2a76a73d549023e481875c6",
28
+ "builtin_tracks/tracks/Replica A08 Long.track": "3e259bd227776ca847d35baaea88b5e8af57cc920643bf71563176bd6554ad65",
29
+ "builtin_tracks/tracks/Replica A09 Sharpest.track": "5362cea3c564dce8f4f22fcd4b798347931dfaa4e65b84624944952b3e0b0d2a",
30
+ "builtin_tracks/tracks/Replica B01 Oval.track": "0df5755150c145a35edc6c8693f429e5b9ff4b12210ba67cbfcb932c58faf158",
31
+ "builtin_tracks/tracks/Replica B02 Snake.track": "210e699b1fa5f2624a2ff0969b73a20af7bc56bf774f4fd282f6109f80bfdb3c",
32
+ "builtin_tracks/tracks/Replica B03 Slalom.track": "a8bab86f93e3072bf27a81a354220c137207b9fc0b548372c8dab93639a18a24",
33
+ "builtin_tracks/tracks/Replica B04 Rally.track": "9d2fc668a7c86aabb9ca9dbfdbd21dff0d099c5d77029aa2ae96b6c7b9efd3f0",
34
+ "builtin_tracks/tracks/Replica B05 Racetrack.track": "d0804ebc17646d2f7c3be65cfe0f6e94033417e75b101a8c598a69131a170079",
35
+ "builtin_tracks/tracks/Replica B06 Hard.track": "8b1a10fd8485405d7f73abca8890f4845145227177c9ac07ac9a1d79f28908f9",
36
+ "builtin_tracks/tracks/Replica B07 Drift.track": "d6d46216882cb63d55b1e8ce81ffa67f1c95ffd0a86a72806b8fd23973c6ce0a",
37
+ "builtin_tracks/tracks/Replica B08 Arctic Circle.track": "229128e86a87089f781b072a4c677ff729cf8488b1d74ad75cfb43655b9f4a16",
38
+ "builtin_tracks/tracks/Replica B09 Checkered.track": "bec4dbd0edc35e0e4f4d1035c608a0c56bbc99e7301f640f8e2eddba0100b2fe",
39
+ "builtin_tracks/tracks/Replica R01 Blitzring.track": "14b52a7cbbf7de5606c772c74730c0e8776f39ed72955fef5ae1f7c2d8ccef77",
40
+ "builtin_tracks/tracks/Replica R02 Desert Rally.track": "653286b00f2f04450e698d8b8e9d4ecb268064b323b182d2de9db7d017b22238",
41
+ "builtin_tracks/tracks/Replica R03 Glacier.track": "0e1b42ce51ae91a8702e173013a090d00145e518bb47d7a659cb1d1fdff011b5",
42
+ "builtin_tracks/tracks/Replica R04 Truck Maze.track": "d7b89d64e118506e6cec259057886d9267ca4c6fab570e7ba0d6641e8f822f11",
43
+ "builtin_tracks/tracks/Replica R05 Endurance 500.track": "dde36ad5f627bce65d45a96d46a68497f8d446f6011c9df19ee51ce71375cba8",
44
+ "builtin_tracks/tracks/Replica R06 Mix.track": "9de8d912a59001ea13baa7f1b4f92884b8cddf91978f31e19f3237975713f739",
45
+ "builtin_tracks/tracks/Replica R07 Mirage Marina.track": "8c6764f3accb1a8372d910d57f4f681572dd40c590c4a3d03517379bb360fcd7",
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": "1c5446c6d192c3da25d370aba88d94f685af94acb175f2d4f5499bfa4098a628",
50
  "delivery.py": "4f5a4e45df92e5cbfdef6eb449ede9ba26217fe24da376fafddae5cbbb73847a",
51
  "gpu_tickets.py": "c32cb5de751d49d3e1cd970c7d6328a42ebe71602dd9fd3788c872eef42611da",
52
  "hf-auth.js": "743fa2b62c611fcc6064664691e133efb5d163412955b2a9d0a562a428412864",
53
  "hf_identity.py": "6993d0238ada835606dbdc3275c17a3fe5a5cac5ad2156ab78230acf2d051eba",
54
+ "index.html": "11237dcf43bb2744cbb83982e44fa4db35da81c24d5c0df48d896f8973bac0b5",
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",
STORAGE_BOUNDARY.md CHANGED
@@ -7,6 +7,8 @@ same settings contract is used independently of the selected storage policy.
7
  |---|---|---|
8
  | Recipe library | Injected storage adapter, browser localStorage | Explicit save; own-key clear; settings/names/references only |
9
  | Track / network editor | Browser File/Blob objects | Page memory; selected for upload only on Start |
 
 
10
  | Worker inputs / intermediate files | Temporary directory | Removed before successful result publication |
11
  | GPU pending inputs | Opaque single-use ticket plus memory store | Dispatch, fixed 120-second expiry, or shutdown |
12
  | Single-run output | Memory result store and random job key | Receipt ACK in automatic mode, manual delete, fixed 30-minute expiry, or shutdown |
 
7
  |---|---|---|
8
  | Recipe library | Injected storage adapter, browser localStorage | Explicit save; own-key clear; settings/names/references only |
9
  | Track / network editor | Browser File/Blob objects | Page memory; selected for upload only on Start |
10
+ | Built-in replica library | Read-only, allow-listed release files; anonymous catalog/file endpoints | Intentionally persistent shared references; not erased by job deletion; user uploads never enter the catalog |
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 |
TRACK_LIBRARY.md ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Built-in editor-format replica tracks
2
+
3
+ This read-only library contains 28 programmatically reconstructed editor-format
4
+ replicas: A01–A09, B01–B09, R01–R09 and The Champions Trial. The operator explicitly
5
+ approved this replica bundle for inclusion. The files are not editor-authored,
6
+ clean-room creations or the original packaged track files. Original layout data
7
+ was used; a new file format/serialization is not a claim of independent origin.
8
+
9
+ Source schema: ald-editor-format-replicas-v1, run-r2-dummy-stars. The shipped
10
+ catalog declares the method and editor_authored=false / clean_room=false, and
11
+ contains each file's SHA-256 and byte count. Private provenance paths, original
12
+ packaged files, artwork, textures, opponents/controllers, original race parameters
13
+ and the native geometry catalog are not part of this library.
14
+
15
+ Training-track numeric challenge conditions were preserved. Race replicas use
16
+ dummy lap stars rather than claiming to reproduce opponent challenges. The HF
17
+ worker does not evaluate these conditions or grant campaign stars. Availability
18
+ in this selector is not a claim of official game approval, legal clearance,
19
+ game-editor load verification, physics parity or leaderboard qualification.
20
+
21
+ Track selection and Training track are synchronized controls for one active
22
+ input. Upload a custom track remains available. Selecting a built-in clears the
23
+ custom file selection; choosing an upload switches back to upload mode. Built-in
24
+ selection survives completed runs in this page, but is not written to cookies,
25
+ localStorage, recipes, or account storage. Network selection is still explicit.
26
+ The renderer remains a placeholder.
27
+
28
+ The public app exposes only catalog-listed IDs and hash-checked replica bytes.
29
+ No directory browsing, caller-selected paths, remote track URLs or extraction
30
+ from game binaries is supported. CPU and GPU use the same existing bounded input
31
+ contract. Client and server both check reference-file size/SHA-256.
32
+
33
+ These reusable reference tracks are intentionally part of the app package, not
34
+ private job data. Job deletion removes the submitted copies, temporary work and
35
+ stored result, not this shared library. Built-in files are retrievable by app
36
+ visitors even while HF source visibility remains Protected. User-uploaded
37
+ tracks/networks never enter this catalog and retain the existing deletion rules.
builtin_tracks.py ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Read-only, hash-checked reference tracks; separate from ephemeral job data."""
2
+ import hashlib
3
+ import json
4
+ from pathlib import Path
5
+ import re
6
+
7
+
8
+ class TrackLibrary:
9
+ def __init__(self, root):
10
+ self.root=Path(root).resolve()
11
+ self._entries={}
12
+ catalog=self.root/'catalog.json'
13
+ if not catalog.exists():return # Older/local upload-only installations.
14
+ if catalog.stat().st_size>256*1024:raise ValueError('Track catalog too large')
15
+ data=json.loads(catalog.read_text())
16
+ if data.get('schema')!='ald-editor-format-replicas-v1':raise ValueError('Unknown track catalog')
17
+ tracks=data['tracks']
18
+ if not isinstance(tracks,list) or not 1<=len(tracks)<=128:raise ValueError('Track count')
19
+ for entry in tracks:
20
+ identifier=entry['id'];relative=Path(entry['file'])
21
+ if not isinstance(identifier,str) or not re.fullmatch(r'[a-z0-9-]{1,80}',identifier):
22
+ raise ValueError('Track ID')
23
+ if identifier in self._entries:raise ValueError('Duplicate track ID')
24
+ if len(relative.parts)!=2 or relative.parts[0]!='tracks' or relative.suffix!='.track':
25
+ raise ValueError('Track path')
26
+ path=self.root/relative
27
+ if path.is_symlink() or path.resolve()!=path or not path.is_file():raise ValueError('Track path')
28
+ size=entry['bytes'];digest=entry['sha256']
29
+ if type(size)!=int or not 1<=size<=1024*1024 or not re.fullmatch(r'[a-f0-9]{64}',digest):
30
+ raise ValueError('Track size/hash')
31
+ for label in ('display_name','reference_label'):
32
+ if not isinstance(entry[label],str) or not 1<=len(entry[label])<=100:raise ValueError('Track label')
33
+ public={key:entry[key] for key in ('id','display_name','reference_label','bytes','sha256')}
34
+ self._entries[identifier]=(path,public)
35
+ self.read(identifier)
36
+
37
+ def catalog(self):
38
+ # Never expose private provenance source paths or arbitrary input fields.
39
+ return {'schema':'ald-builtin-track-library-v1',
40
+ 'method':'programmatically reconstructed editor-format replicas',
41
+ 'editor_authored':False,'clean_room':False,
42
+ 'challenge_runtime_status':'not evaluated by this app',
43
+ 'tracks':[dict(entry) for _,entry in self._entries.values()]}
44
+
45
+ def read(self, identifier):
46
+ if identifier not in self._entries:raise KeyError(identifier)
47
+ path,entry=self._entries[identifier]
48
+ if path.is_symlink() or path.resolve()!=path or path.stat().st_size!=entry['bytes']:
49
+ raise ValueError('Track validation failed')
50
+ payload=path.read_bytes()
51
+ if hashlib.sha256(payload).hexdigest()!=entry['sha256']:raise ValueError('Track validation failed')
52
+ return payload
53
+
54
+ def members(self):
55
+ return [(path.relative_to(self.root).as_posix(),path) for path,_ in self._entries.values()]
builtin_tracks/catalog.json ADDED
@@ -0,0 +1,494 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "schema": "ald-editor-format-replicas-v1",
3
+ "method": "programmatically reconstructed from private original layout data",
4
+ "editor_authored": false,
5
+ "clean_room": false,
6
+ "original_packaged_track_files_included": false,
7
+ "artwork_or_opponent_controllers_included": false,
8
+ "original_race_parameters_included": false,
9
+ "native_geometry_catalog_included": false,
10
+ "integration_status": "local_input_and_native_import_verified_not_deployed",
11
+ "challenge_runtime_status": "definitions_transferred_not_evaluated_by_current_HF_worker",
12
+ "tracks": [
13
+ {
14
+ "file": "tracks/Replica A01 Beginner.track",
15
+ "display_name": "Replica A01 Beginner",
16
+ "reference_label": "A01 Beginner",
17
+ "id": "2be5df89-4743-5df8-bf8e-34381cd5e65a",
18
+ "tile_count": 8,
19
+ "challenge_count": 3,
20
+ "challenge_source": "preserved_numeric_conditions",
21
+ "original_campaign_unlock_stars": 0,
22
+ "sha256": "ca5749537450430794e2eade2e0ac72fa141a4f225e13e2f8ef842abb948ff15",
23
+ "bytes": 453,
24
+ "expanded_bytes": 1349,
25
+ "native_scene_equal_to_reference_layout": true,
26
+ "game_editor_load_verified": false
27
+ },
28
+ {
29
+ "file": "tracks/Replica A02 Sharp Turns.track",
30
+ "display_name": "Replica A02 Sharp Turns",
31
+ "reference_label": "A02 Sharp Turns",
32
+ "id": "ffb40946-a112-528e-b08f-d892a0b9b2a1",
33
+ "tile_count": 8,
34
+ "challenge_count": 3,
35
+ "challenge_source": "preserved_numeric_conditions",
36
+ "original_campaign_unlock_stars": 0,
37
+ "sha256": "097f1ea8edf041112b690d0638075630716ddc03c7d0b1980ddcbeaf5071c8d4",
38
+ "bytes": 465,
39
+ "expanded_bytes": 1379,
40
+ "native_scene_equal_to_reference_layout": true,
41
+ "game_editor_load_verified": false
42
+ },
43
+ {
44
+ "file": "tracks/Replica A03 High Speed.track",
45
+ "display_name": "Replica A03 High Speed",
46
+ "reference_label": "A03 High Speed",
47
+ "id": "d3bcd33c-09d4-5783-8110-85ea7cb3fa94",
48
+ "tile_count": 14,
49
+ "challenge_count": 3,
50
+ "challenge_source": "preserved_numeric_conditions",
51
+ "original_campaign_unlock_stars": 0,
52
+ "sha256": "88917c63847be1854b989bb28a23af7eeacb964c3e7df9579953aebc9496e6af",
53
+ "bytes": 528,
54
+ "expanded_bytes": 2041,
55
+ "native_scene_equal_to_reference_layout": true,
56
+ "game_editor_load_verified": false
57
+ },
58
+ {
59
+ "file": "tracks/Replica A04 Dirt.track",
60
+ "display_name": "Replica A04 Dirt",
61
+ "reference_label": "A04 Dirt",
62
+ "id": "ed26fc72-beb3-54e0-999a-78b840fe13ba",
63
+ "tile_count": 12,
64
+ "challenge_count": 3,
65
+ "challenge_source": "preserved_numeric_conditions",
66
+ "original_campaign_unlock_stars": 0,
67
+ "sha256": "7f4fe58516227b15898d14bb0abb9a0856126d24fcd793884f051f7a4fae521d",
68
+ "bytes": 547,
69
+ "expanded_bytes": 1863,
70
+ "native_scene_equal_to_reference_layout": true,
71
+ "game_editor_load_verified": false
72
+ },
73
+ {
74
+ "file": "tracks/Replica A05 Two Terrains.track",
75
+ "display_name": "Replica A05 Two Terrains",
76
+ "reference_label": "A05 Two Terrains",
77
+ "id": "06781f37-be14-5dfb-92fa-4f77e29607d9",
78
+ "tile_count": 16,
79
+ "challenge_count": 3,
80
+ "challenge_source": "preserved_numeric_conditions",
81
+ "original_campaign_unlock_stars": 0,
82
+ "sha256": "c4ee2842920d99cdfe3eebdcad59a77e24b626380acef0d02a39ea1e23823e2a",
83
+ "bytes": 567,
84
+ "expanded_bytes": 2261,
85
+ "native_scene_equal_to_reference_layout": true,
86
+ "game_editor_load_verified": false
87
+ },
88
+ {
89
+ "file": "tracks/Replica A06 Ice.track",
90
+ "display_name": "Replica A06 Ice",
91
+ "reference_label": "A06 Ice",
92
+ "id": "16801fef-ba6a-5ea6-aab0-d191e3ceecf4",
93
+ "tile_count": 10,
94
+ "challenge_count": 3,
95
+ "challenge_source": "preserved_numeric_conditions",
96
+ "original_campaign_unlock_stars": 0,
97
+ "sha256": "fccb9a159a06d1b986c6fe7d5bb89c0cabad3a005531f4e0d71f6e37254ada34",
98
+ "bytes": 508,
99
+ "expanded_bytes": 1661,
100
+ "native_scene_equal_to_reference_layout": true,
101
+ "game_editor_load_verified": false
102
+ },
103
+ {
104
+ "file": "tracks/Replica A07 Three Terrains.track",
105
+ "display_name": "Replica A07 Three Terrains",
106
+ "reference_label": "A07 Three Terrains",
107
+ "id": "5c4aaf13-b594-5ec3-b836-efec5fab7887",
108
+ "tile_count": 12,
109
+ "challenge_count": 3,
110
+ "challenge_source": "preserved_numeric_conditions",
111
+ "original_campaign_unlock_stars": 0,
112
+ "sha256": "a8fa652ad451e2702a23d5f3429eb0b6a6408bf6a2a76a73d549023e481875c6",
113
+ "bytes": 533,
114
+ "expanded_bytes": 1858,
115
+ "native_scene_equal_to_reference_layout": true,
116
+ "game_editor_load_verified": false
117
+ },
118
+ {
119
+ "file": "tracks/Replica A08 Long.track",
120
+ "display_name": "Replica A08 Long",
121
+ "reference_label": "A08 Long",
122
+ "id": "1a18c7cc-f0fd-5055-9799-2a4abde8fed3",
123
+ "tile_count": 36,
124
+ "challenge_count": 3,
125
+ "challenge_source": "preserved_numeric_conditions",
126
+ "original_campaign_unlock_stars": 0,
127
+ "sha256": "3e259bd227776ca847d35baaea88b5e8af57cc920643bf71563176bd6554ad65",
128
+ "bytes": 683,
129
+ "expanded_bytes": 4140,
130
+ "native_scene_equal_to_reference_layout": true,
131
+ "game_editor_load_verified": false
132
+ },
133
+ {
134
+ "file": "tracks/Replica A09 Sharpest.track",
135
+ "display_name": "Replica A09 Sharpest",
136
+ "reference_label": "A09 Sharpest",
137
+ "id": "9328cb63-d50c-57c3-972b-6bcb9ab475a9",
138
+ "tile_count": 16,
139
+ "challenge_count": 3,
140
+ "challenge_source": "preserved_numeric_conditions",
141
+ "original_campaign_unlock_stars": 0,
142
+ "sha256": "5362cea3c564dce8f4f22fcd4b798347931dfaa4e65b84624944952b3e0b0d2a",
143
+ "bytes": 584,
144
+ "expanded_bytes": 2259,
145
+ "native_scene_equal_to_reference_layout": true,
146
+ "game_editor_load_verified": false
147
+ },
148
+ {
149
+ "file": "tracks/Replica B01 Oval.track",
150
+ "display_name": "Replica B01 Oval",
151
+ "reference_label": "B01 Oval",
152
+ "id": "787f73f5-3b8c-5d95-b0e3-0016ed076970",
153
+ "tile_count": 6,
154
+ "challenge_count": 3,
155
+ "challenge_source": "preserved_numeric_conditions",
156
+ "original_campaign_unlock_stars": 0,
157
+ "sha256": "0df5755150c145a35edc6c8693f429e5b9ff4b12210ba67cbfcb932c58faf158",
158
+ "bytes": 477,
159
+ "expanded_bytes": 1291,
160
+ "native_scene_equal_to_reference_layout": true,
161
+ "game_editor_load_verified": false
162
+ },
163
+ {
164
+ "file": "tracks/Replica B02 Snake.track",
165
+ "display_name": "Replica B02 Snake",
166
+ "reference_label": "B02 Snake",
167
+ "id": "e2358ccd-201e-570c-9f61-ce0994c71935",
168
+ "tile_count": 14,
169
+ "challenge_count": 3,
170
+ "challenge_source": "preserved_numeric_conditions",
171
+ "original_campaign_unlock_stars": 0,
172
+ "sha256": "210e699b1fa5f2624a2ff0969b73a20af7bc56bf774f4fd282f6109f80bfdb3c",
173
+ "bytes": 555,
174
+ "expanded_bytes": 2064,
175
+ "native_scene_equal_to_reference_layout": true,
176
+ "game_editor_load_verified": false
177
+ },
178
+ {
179
+ "file": "tracks/Replica B03 Slalom.track",
180
+ "display_name": "Replica B03 Slalom",
181
+ "reference_label": "B03 Slalom",
182
+ "id": "04da6fdb-0330-57d5-920f-3001dfe4b8c0",
183
+ "tile_count": 14,
184
+ "challenge_count": 3,
185
+ "challenge_source": "preserved_numeric_conditions",
186
+ "original_campaign_unlock_stars": 0,
187
+ "sha256": "a8bab86f93e3072bf27a81a354220c137207b9fc0b548372c8dab93639a18a24",
188
+ "bytes": 530,
189
+ "expanded_bytes": 2077,
190
+ "native_scene_equal_to_reference_layout": true,
191
+ "game_editor_load_verified": false
192
+ },
193
+ {
194
+ "file": "tracks/Replica B04 Rally.track",
195
+ "display_name": "Replica B04 Rally",
196
+ "reference_label": "B04 Rally",
197
+ "id": "a0be65c0-4142-5d43-b00e-63f56e640d48",
198
+ "tile_count": 20,
199
+ "challenge_count": 3,
200
+ "challenge_source": "preserved_numeric_conditions",
201
+ "original_campaign_unlock_stars": 0,
202
+ "sha256": "9d2fc668a7c86aabb9ca9dbfdbd21dff0d099c5d77029aa2ae96b6c7b9efd3f0",
203
+ "bytes": 648,
204
+ "expanded_bytes": 2743,
205
+ "native_scene_equal_to_reference_layout": true,
206
+ "game_editor_load_verified": false
207
+ },
208
+ {
209
+ "file": "tracks/Replica B05 Racetrack.track",
210
+ "display_name": "Replica B05 Racetrack",
211
+ "reference_label": "B05 Racetrack",
212
+ "id": "7a62028b-e2eb-59db-81a0-8e5933f2a09d",
213
+ "tile_count": 22,
214
+ "challenge_count": 3,
215
+ "challenge_source": "preserved_numeric_conditions",
216
+ "original_campaign_unlock_stars": 0,
217
+ "sha256": "d0804ebc17646d2f7c3be65cfe0f6e94033417e75b101a8c598a69131a170079",
218
+ "bytes": 627,
219
+ "expanded_bytes": 2884,
220
+ "native_scene_equal_to_reference_layout": true,
221
+ "game_editor_load_verified": false
222
+ },
223
+ {
224
+ "file": "tracks/Replica B06 Hard.track",
225
+ "display_name": "Replica B06 Hard",
226
+ "reference_label": "B06 Hard",
227
+ "id": "251fb67e-1f1e-537e-8c85-c3688f08198f",
228
+ "tile_count": 30,
229
+ "challenge_count": 3,
230
+ "challenge_source": "preserved_numeric_conditions",
231
+ "original_campaign_unlock_stars": 0,
232
+ "sha256": "8b1a10fd8485405d7f73abca8890f4845145227177c9ac07ac9a1d79f28908f9",
233
+ "bytes": 674,
234
+ "expanded_bytes": 3625,
235
+ "native_scene_equal_to_reference_layout": true,
236
+ "game_editor_load_verified": false
237
+ },
238
+ {
239
+ "file": "tracks/Replica B07 Drift.track",
240
+ "display_name": "Replica B07 Drift",
241
+ "reference_label": "B07 Drift",
242
+ "id": "dfef0a18-46ac-5ece-9956-b5c843e9d588",
243
+ "tile_count": 16,
244
+ "challenge_count": 3,
245
+ "challenge_source": "preserved_numeric_conditions",
246
+ "original_campaign_unlock_stars": 0,
247
+ "sha256": "d6d46216882cb63d55b1e8ce81ffa67f1c95ffd0a86a72806b8fd23973c6ce0a",
248
+ "bytes": 570,
249
+ "expanded_bytes": 2282,
250
+ "native_scene_equal_to_reference_layout": true,
251
+ "game_editor_load_verified": false
252
+ },
253
+ {
254
+ "file": "tracks/Replica B08 Arctic Circle.track",
255
+ "display_name": "Replica B08 Arctic Circle",
256
+ "reference_label": "B08 Arctic Circle",
257
+ "id": "8b60d3b0-d694-592e-a85b-1d77d3fe7c0f",
258
+ "tile_count": 28,
259
+ "challenge_count": 3,
260
+ "challenge_source": "preserved_numeric_conditions",
261
+ "original_campaign_unlock_stars": 0,
262
+ "sha256": "229128e86a87089f781b072a4c677ff729cf8488b1d74ad75cfb43655b9f4a16",
263
+ "bytes": 709,
264
+ "expanded_bytes": 3519,
265
+ "native_scene_equal_to_reference_layout": true,
266
+ "game_editor_load_verified": false
267
+ },
268
+ {
269
+ "file": "tracks/Replica B09 Checkered.track",
270
+ "display_name": "Replica B09 Checkered",
271
+ "reference_label": "B09 Checkered",
272
+ "id": "61561797-8ffb-5521-a607-b5fdfca94783",
273
+ "tile_count": 48,
274
+ "challenge_count": 3,
275
+ "challenge_source": "preserved_numeric_conditions",
276
+ "original_campaign_unlock_stars": 0,
277
+ "sha256": "bec4dbd0edc35e0e4f4d1035c608a0c56bbc99e7301f640f8e2eddba0100b2fe",
278
+ "bytes": 810,
279
+ "expanded_bytes": 5421,
280
+ "native_scene_equal_to_reference_layout": true,
281
+ "game_editor_load_verified": false
282
+ },
283
+ {
284
+ "file": "tracks/Replica R01 Blitzring.track",
285
+ "display_name": "Replica R01 Blitzring",
286
+ "reference_label": "R01 Blitzring",
287
+ "id": "31fc3eb7-f2cc-5e4e-9fbf-c02f8e040ff7",
288
+ "tile_count": 18,
289
+ "challenge_count": 3,
290
+ "challenge_source": "dummy_lap_challenges",
291
+ "original_campaign_unlock_stars": 0,
292
+ "sha256": "14b52a7cbbf7de5606c772c74730c0e8776f39ed72955fef5ae1f7c2d8ccef77",
293
+ "bytes": 518,
294
+ "expanded_bytes": 2316,
295
+ "native_scene_equal_to_reference_layout": true,
296
+ "game_editor_load_verified": false,
297
+ "dummy_lap_counts": [
298
+ 1,
299
+ 2,
300
+ 3
301
+ ],
302
+ "original_race_behavior_included": false
303
+ },
304
+ {
305
+ "file": "tracks/Replica R02 Desert Rally.track",
306
+ "display_name": "Replica R02 Desert Rally",
307
+ "reference_label": "R02 Desert Rally",
308
+ "id": "17d76866-6c6b-5b04-aaa5-32a03a61183b",
309
+ "tile_count": 22,
310
+ "challenge_count": 3,
311
+ "challenge_source": "dummy_lap_challenges",
312
+ "original_campaign_unlock_stars": 0,
313
+ "sha256": "653286b00f2f04450e698d8b8e9d4ecb268064b323b182d2de9db7d017b22238",
314
+ "bytes": 552,
315
+ "expanded_bytes": 2750,
316
+ "native_scene_equal_to_reference_layout": true,
317
+ "game_editor_load_verified": false,
318
+ "dummy_lap_counts": [
319
+ 1,
320
+ 2,
321
+ 3
322
+ ],
323
+ "original_race_behavior_included": false
324
+ },
325
+ {
326
+ "file": "tracks/Replica R03 Glacier.track",
327
+ "display_name": "Replica R03 Glacier",
328
+ "reference_label": "R03 Glacier",
329
+ "id": "2377f26c-1aff-5a32-bda4-27582a7bc62e",
330
+ "tile_count": 14,
331
+ "challenge_count": 3,
332
+ "challenge_source": "dummy_lap_challenges",
333
+ "original_campaign_unlock_stars": 0,
334
+ "sha256": "0e1b42ce51ae91a8702e173013a090d00145e518bb47d7a659cb1d1fdff011b5",
335
+ "bytes": 484,
336
+ "expanded_bytes": 1942,
337
+ "native_scene_equal_to_reference_layout": true,
338
+ "game_editor_load_verified": false,
339
+ "dummy_lap_counts": [
340
+ 1,
341
+ 2,
342
+ 3
343
+ ],
344
+ "original_race_behavior_included": false
345
+ },
346
+ {
347
+ "file": "tracks/Replica R04 Truck Maze.track",
348
+ "display_name": "Replica R04 Truck Maze",
349
+ "reference_label": "R04 Truck Maze",
350
+ "id": "54d93736-7aca-5bf6-9f04-6baddaa8f720",
351
+ "tile_count": 22,
352
+ "challenge_count": 3,
353
+ "challenge_source": "dummy_lap_challenges",
354
+ "original_campaign_unlock_stars": 0,
355
+ "sha256": "d7b89d64e118506e6cec259057886d9267ca4c6fab570e7ba0d6641e8f822f11",
356
+ "bytes": 546,
357
+ "expanded_bytes": 2712,
358
+ "native_scene_equal_to_reference_layout": true,
359
+ "game_editor_load_verified": false,
360
+ "dummy_lap_counts": [
361
+ 1,
362
+ 2,
363
+ 3
364
+ ],
365
+ "original_race_behavior_included": false
366
+ },
367
+ {
368
+ "file": "tracks/Replica R05 Endurance 500.track",
369
+ "display_name": "Replica R05 Endurance 500",
370
+ "reference_label": "R05 Endurance 500",
371
+ "id": "6310df17-ac5d-5c88-9dea-35a3e125f4fb",
372
+ "tile_count": 8,
373
+ "challenge_count": 3,
374
+ "challenge_source": "dummy_lap_challenges",
375
+ "original_campaign_unlock_stars": 0,
376
+ "sha256": "dde36ad5f627bce65d45a96d46a68497f8d446f6011c9df19ee51ce71375cba8",
377
+ "bytes": 421,
378
+ "expanded_bytes": 1323,
379
+ "native_scene_equal_to_reference_layout": true,
380
+ "game_editor_load_verified": false,
381
+ "dummy_lap_counts": [
382
+ 1,
383
+ 2,
384
+ 3
385
+ ],
386
+ "original_race_behavior_included": false
387
+ },
388
+ {
389
+ "file": "tracks/Replica R06 Mix.track",
390
+ "display_name": "Replica R06 Mix",
391
+ "reference_label": "R06 Mix",
392
+ "id": "88f19bd6-6793-5afd-a6d5-b57e4e1dcc8b",
393
+ "tile_count": 16,
394
+ "challenge_count": 3,
395
+ "challenge_source": "dummy_lap_challenges",
396
+ "original_campaign_unlock_stars": 0,
397
+ "sha256": "9de8d912a59001ea13baa7f1b4f92884b8cddf91978f31e19f3237975713f739",
398
+ "bytes": 506,
399
+ "expanded_bytes": 2141,
400
+ "native_scene_equal_to_reference_layout": true,
401
+ "game_editor_load_verified": false,
402
+ "dummy_lap_counts": [
403
+ 1,
404
+ 2,
405
+ 3
406
+ ],
407
+ "original_race_behavior_included": false
408
+ },
409
+ {
410
+ "file": "tracks/Replica R07 Mirage Marina.track",
411
+ "display_name": "Replica R07 Mirage Marina",
412
+ "reference_label": "R07 Mirage Marina",
413
+ "id": "a7d250e1-1ad3-575c-aec4-abff2fb78ace",
414
+ "tile_count": 34,
415
+ "challenge_count": 3,
416
+ "challenge_source": "dummy_lap_challenges",
417
+ "original_campaign_unlock_stars": 0,
418
+ "sha256": "8c6764f3accb1a8372d910d57f4f681572dd40c590c4a3d03517379bb360fcd7",
419
+ "bytes": 669,
420
+ "expanded_bytes": 3912,
421
+ "native_scene_equal_to_reference_layout": true,
422
+ "game_editor_load_verified": false,
423
+ "dummy_lap_counts": [
424
+ 1,
425
+ 2,
426
+ 3
427
+ ],
428
+ "original_race_behavior_included": false
429
+ },
430
+ {
431
+ "file": "tracks/Replica R08 Demolition Derby.track",
432
+ "display_name": "Replica R08 Demolition Derby",
433
+ "reference_label": "R08 Demolition Derby",
434
+ "id": "fbac2103-2234-5574-80b3-d94daf816f97",
435
+ "tile_count": 10,
436
+ "challenge_count": 3,
437
+ "challenge_source": "dummy_lap_challenges",
438
+ "original_campaign_unlock_stars": 0,
439
+ "sha256": "6f11a9ffbcb477c9d19964566b1b612d2a94675605246e93e21f27bbbdb357ef",
440
+ "bytes": 447,
441
+ "expanded_bytes": 1518,
442
+ "native_scene_equal_to_reference_layout": true,
443
+ "game_editor_load_verified": false,
444
+ "dummy_lap_counts": [
445
+ 1,
446
+ 2,
447
+ 3
448
+ ],
449
+ "original_race_behavior_included": false
450
+ },
451
+ {
452
+ "file": "tracks/Replica R09 Eau Noir.track",
453
+ "display_name": "Replica R09 Eau Noir",
454
+ "reference_label": "R09 Eau Noir",
455
+ "id": "f97eca66-0455-5e8d-af0c-bc8fd3b11569",
456
+ "tile_count": 28,
457
+ "challenge_count": 3,
458
+ "challenge_source": "dummy_lap_challenges",
459
+ "original_campaign_unlock_stars": 0,
460
+ "sha256": "3ec0a78478cca1a4f0d2d98ac81f40783928adf271b70f0c32d295a6da2cdaa9",
461
+ "bytes": 609,
462
+ "expanded_bytes": 3302,
463
+ "native_scene_equal_to_reference_layout": true,
464
+ "game_editor_load_verified": false,
465
+ "dummy_lap_counts": [
466
+ 1,
467
+ 2,
468
+ 3
469
+ ],
470
+ "original_race_behavior_included": false
471
+ },
472
+ {
473
+ "file": "tracks/Replica The Champions Trial.track",
474
+ "display_name": "Replica The Champions Trial",
475
+ "reference_label": "The Champions Trial",
476
+ "id": "86d13552-32e0-583a-9e95-f8df9717c9da",
477
+ "tile_count": 76,
478
+ "challenge_count": 3,
479
+ "challenge_source": "dummy_lap_challenges",
480
+ "original_campaign_unlock_stars": 81,
481
+ "sha256": "a3bfb76422affc774b44c739b0636d08acb901fa7615b9adcb52c069f79834e1",
482
+ "bytes": 976,
483
+ "expanded_bytes": 8080,
484
+ "native_scene_equal_to_reference_layout": true,
485
+ "game_editor_load_verified": false,
486
+ "dummy_lap_counts": [
487
+ 1,
488
+ 2,
489
+ 3
490
+ ],
491
+ "original_race_behavior_included": false
492
+ }
493
+ ]
494
+ }
builtin_tracks/tracks/Replica A01 Beginner.track ADDED
Binary file (453 Bytes). View file
 
builtin_tracks/tracks/Replica A02 Sharp Turns.track ADDED
Binary file (465 Bytes). View file
 
builtin_tracks/tracks/Replica A03 High Speed.track ADDED
Binary file (528 Bytes). View file
 
builtin_tracks/tracks/Replica A04 Dirt.track ADDED
Binary file (547 Bytes). View file
 
builtin_tracks/tracks/Replica A05 Two Terrains.track ADDED
Binary file (567 Bytes). View file
 
builtin_tracks/tracks/Replica A06 Ice.track ADDED
Binary file (508 Bytes). View file
 
builtin_tracks/tracks/Replica A07 Three Terrains.track ADDED
Binary file (533 Bytes). View file
 
builtin_tracks/tracks/Replica A08 Long.track ADDED
Binary file (683 Bytes). View file
 
builtin_tracks/tracks/Replica A09 Sharpest.track ADDED
Binary file (584 Bytes). View file
 
builtin_tracks/tracks/Replica B01 Oval.track ADDED
Binary file (477 Bytes). View file
 
builtin_tracks/tracks/Replica B02 Snake.track ADDED
Binary file (555 Bytes). View file
 
builtin_tracks/tracks/Replica B03 Slalom.track ADDED
Binary file (530 Bytes). View file
 
builtin_tracks/tracks/Replica B04 Rally.track ADDED
Binary file (648 Bytes). View file
 
builtin_tracks/tracks/Replica B05 Racetrack.track ADDED
Binary file (627 Bytes). View file
 
builtin_tracks/tracks/Replica B06 Hard.track ADDED
Binary file (674 Bytes). View file
 
builtin_tracks/tracks/Replica B07 Drift.track ADDED
Binary file (570 Bytes). View file
 
builtin_tracks/tracks/Replica B08 Arctic Circle.track ADDED
Binary file (709 Bytes). View file
 
builtin_tracks/tracks/Replica B09 Checkered.track ADDED
Binary file (810 Bytes). View file
 
builtin_tracks/tracks/Replica R01 Blitzring.track ADDED
Binary file (518 Bytes). View file
 
builtin_tracks/tracks/Replica R02 Desert Rally.track ADDED
Binary file (552 Bytes). View file
 
builtin_tracks/tracks/Replica R03 Glacier.track ADDED
Binary file (484 Bytes). View file
 
builtin_tracks/tracks/Replica R04 Truck Maze.track ADDED
Binary file (546 Bytes). View file
 
builtin_tracks/tracks/Replica R05 Endurance 500.track ADDED
Binary file (421 Bytes). View file
 
builtin_tracks/tracks/Replica R06 Mix.track ADDED
Binary file (506 Bytes). View file
 
builtin_tracks/tracks/Replica R07 Mirage Marina.track ADDED
Binary file (669 Bytes). View file
 
builtin_tracks/tracks/Replica R08 Demolition Derby.track ADDED
Binary file (447 Bytes). View file
 
builtin_tracks/tracks/Replica R09 Eau Noir.track ADDED
Binary file (609 Bytes). View file
 
builtin_tracks/tracks/Replica The Champions Trial.track ADDED
Binary file (976 Bytes). View file
 
client.js CHANGED
@@ -13,7 +13,10 @@ let batchReceipt = null;
13
  // Display context affects quota guidance, never whether GPU can be selected.
14
  const hostedStandalone = location.hostname.endsWith('.hf.space') && window.self === window.top;
15
  const say = text => { $('status').textContent = text; };
 
 
16
  function buttons() {
 
17
  window.HFAuth?.setBusy(busy || !!job);
18
  window.setTrainingBusy?.(busy || !!job);
19
  window.setEditorBusy?.(busy || !!job);
@@ -118,7 +121,8 @@ $('run').onclick = async () => {
118
  tick(); const progress=setInterval(tick,250);
119
  busy=true; buttons(); say(window.getTrainingSettings?'Processing the training run…':'Processing the bounded test…');
120
  try {
121
- const body={track:await encoded($('track').files[0]),network:await encoded(networkSource()),automatic:$('automatic').checked,backend:$('backend').value};
 
122
  if(window.getTrainingSettings)body.settings=window.getTrainingSettings();
123
  job=await submit(body);localResult=null;
124
  clearInterval(progress);
@@ -128,6 +132,7 @@ $('run').onclick = async () => {
128
  const metric=n=>typeof n==='number'?n.toFixed(3):'Not reported';
129
  $('runSummary').textContent=r?[
130
  'Backend: '+job.backend.toUpperCase(),
 
131
  'Generations: '+r.generations_completed+' / '+r.generations_requested+' · Population: '+r.population,
132
  'Server processing: '+metric(r.elapsed_seconds)+' s',
133
  'Best score: '+metric(r.best_score)+' · Mean score: '+metric(r.mean_score),
@@ -177,7 +182,8 @@ if($('batch_start')){
177
  try{
178
  if(busy||job||!capabilitiesReady)throw Error('Finish the current job and connect first');
179
  plan=window.getBatchPlan();
180
- const track=await encoded($('track').files[0]),original=networkSource();
 
181
  await encoded(original); // Reject missing/oversize inputs before dispatch.
182
  const backend=$('backend').value;
183
  busy=true;batchActive=true;batchStopRequested=false;batchReceipt=null;buttons();
@@ -203,7 +209,7 @@ if($('batch_start')){
203
  line.textContent='Step '+step.step+' · '+step.slot+' · '+step.name+' · completed · '+step.report.generations_completed+' generations · server copy deleted';
204
  $('batch_history').append(line);
205
  }});
206
- batchReceipt={version:1,state:result.state,plan,history,elapsed_seconds:(Date.now()-started)/1000};
207
  $('batch_status').textContent=result.state.toUpperCase()+' · '+history.length+' / '+plan.runs.length+' runs. '+(localResult?'Last received candidate is available on Drive & view.':'No candidate received.');
208
  $('runState').textContent='BATCH '+result.state.toUpperCase()+' — '+history.length+' / '+plan.runs.length+' runs; server copies deleted';
209
  $('runState').style.color=result.state==='completed'?'#62dfb1':'#ffd073';
 
13
  // Display context affects quota guidance, never whether GPU can be selected.
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);
20
  window.HFAuth?.setBusy(busy || !!job);
21
  window.setTrainingBusy?.(busy || !!job);
22
  window.setEditorBusy?.(busy || !!job);
 
121
  tick(); const progress=setInterval(tick,250);
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);
 
132
  const metric=n=>typeof n==='number'?n.toFixed(3):'Not reported';
133
  $('runSummary').textContent=r?[
134
  'Backend: '+job.backend.toUpperCase(),
135
+ 'Track: '+(trackInfo?.source==='builtin'?trackInfo.display_name:'Custom upload'),
136
  'Generations: '+r.generations_completed+' / '+r.generations_requested+' · Population: '+r.population,
137
  'Server processing: '+metric(r.elapsed_seconds)+' s',
138
  'Best score: '+metric(r.best_score)+' · Mean score: '+metric(r.mean_score),
 
182
  try{
183
  if(busy||job||!capabilitiesReady)throw Error('Finish the current job and connect first');
184
  plan=window.getBatchPlan();
185
+ busy=true;buttons(); // Freeze both selectors before an asynchronous track fetch.
186
+ const track=await encoded(await trackSource()),original=networkSource();
187
  await encoded(original); // Reject missing/oversize inputs before dispatch.
188
  const backend=$('backend').value;
189
  busy=true;batchActive=true;batchStopRequested=false;batchReceipt=null;buttons();
 
209
  line.textContent='Step '+step.step+' · '+step.slot+' · '+step.name+' · completed · '+step.report.generations_completed+' generations · server copy deleted';
210
  $('batch_history').append(line);
211
  }});
212
+ batchReceipt={version:1,state:result.state,plan,track:trackLibrary?.info()??{source:'upload'},history,elapsed_seconds:(Date.now()-started)/1000};
213
  $('batch_status').textContent=result.state.toUpperCase()+' · '+history.length+' / '+plan.runs.length+' runs. '+(localResult?'Last received candidate is available on Drive & view.':'No candidate received.');
214
  $('runState').textContent='BATCH '+result.state.toUpperCase()+' — '+history.length+' / '+plan.runs.length+' runs; server copies deleted';
215
  $('runState').style.color=result.state==='completed'?'#62dfb1':'#ffd073';
index.html CHANGED
@@ -7,6 +7,9 @@
7
  <p><label for="backend">Compute</label><select id="backend" disabled><option value="cpu">CPU — no GPU allowance</option><option id="gpuOption" value="gpu" disabled>GPU — uses GPU allowance</option></select></p><p id="backendNote" class="hint">Checking available backends…</p>
8
  <button id="retry" type="button">Retry connection</button>
9
  <p><button id="hfSignIn" type="button" disabled>Sign in with Hugging Face</button> <button id="hfSignOut" type="button" disabled>Sign out of this app</button> <button id="hfVerify" type="button" disabled>Verify HF identity — no GPU</button></p><p id="hfIdentity" role="status" class="hint">CPU needs no sign-in. Checking optional HF sign-in…</p>
 
 
 
10
  <p><label>Track (.track) <input id="track" type="file" accept=".track"></label></p>
11
  <p><label>Formula network (.evolution) <input id="network" type="file" accept=".evolution"></label></p>
12
  <p id="networkChoice" role="status">Choose an uploaded file or use a network from the browser editor.</p><p><label><input id="automatic" type="checkbox" checked> Automatically delete server-side job data after receiving the result</label></p>
@@ -18,7 +21,7 @@
18
  <pre id="runSummary" style="white-space:pre-wrap;line-height:1.7" aria-live="polite"></pre>
19
  <p id="deadline"></p><p id="status" role="status">Ready. Inputs remain on this device until you run the test.</p>
20
  <details><summary>Effective training settings</summary><pre id="effectiveSettings"></pre></details><details><summary>Generation results</summary><pre id="generationHistory"></pre></details><details><summary>Star challenges — not evaluated</summary><p>The current runner has star-challenge reporting. Its evaluator and required statistics have not been ported to HF; no star result is inferred from a completed test.</p></details><h2>Selected track &amp; terrain</h2><div class="map" role="img" aria-label="Track map placeholder"><strong>Track map</strong><p>Renderer not connected yet.</p></div></section></div>
21
- </div><section id="training" class="pane" hidden><div class="card"><h2>Training settings</h2><p class="hint">Choose the track on Drive & view. Choose the training settings and reward mix here, then start the run on Drive & view. Recipes and batch sequences are saved in this browser.</p><div id="training_controls"><label for="training_ticks">Simulated ticks per generation</label><input id="training_ticks" type="number" min="1" max="18000" value="60"><small>60 ticks = one simulated second. Current preview limit: population × generations × ticks ≤ 4,000,000; execution timeout 25 seconds.</small>
22
  <div class="row"><div><label for="population">Population</label><input id="population" type="number" min="1" max="128" value="8" disabled><small>Population limits will follow the selected compute allocation.</small></div><div><label for="generations">Generations</label><input id="generations" type="number" min="1" max="1000" value="30" disabled><small>1–1,000; try 20–50 before review.</small></div></div>
23
  <label id="mutation_label" for="mutation">Mutation rate</label><input id="mutation" type="number" min="0" max="4.2" step="0.01" value="0.1" disabled><small>Mutation settings are passed to the upstream simulator.</small>
24
 
@@ -288,6 +291,85 @@
288
  message('Batch '+batch.slot+' loaded. Loading a batch does not start it.');
289
  });
290
  })();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
291
  </script><script src="/client.js"></script><script src="/hf-auth.js"></script><script>'use strict';
292
  // Navigation only. Editor and training/storage adapters are separate layers.
293
  document.querySelectorAll('[data-tab]').forEach(button=>button.addEventListener('click',()=>{
 
7
  <p><label for="backend">Compute</label><select id="backend" disabled><option value="cpu">CPU — no GPU allowance</option><option id="gpuOption" value="gpu" disabled>GPU — uses GPU allowance</option></select></p><p id="backendNote" class="hint">Checking available backends…</p>
8
  <button id="retry" type="button">Retry connection</button>
9
  <p><button id="hfSignIn" type="button" disabled>Sign in with Hugging Face</button> <button id="hfSignOut" type="button" disabled>Sign out of this app</button> <button id="hfVerify" type="button" disabled>Verify HF identity — no GPU</button></p><p id="hfIdentity" role="status" class="hint">CPU needs no sign-in. Checking optional HF sign-in…</p>
10
+ <p><label for="trackPresetDrive">Track selection</label><select id="trackPresetDrive" data-track-library disabled><option value="">Upload a custom track</option></select></p>
11
+ <p data-track-status role="status" class="hint">Loading built-in replica tracks…</p>
12
+ <p class="hint">Built-in replicas are reconstructed editor-format layouts, not editor-authored or official packaged files. Star conditions are not evaluated.</p>
13
  <p><label>Track (.track) <input id="track" type="file" accept=".track"></label></p>
14
  <p><label>Formula network (.evolution) <input id="network" type="file" accept=".evolution"></label></p>
15
  <p id="networkChoice" role="status">Choose an uploaded file or use a network from the browser editor.</p><p><label><input id="automatic" type="checkbox" checked> Automatically delete server-side job data after receiving the result</label></p>
 
21
  <pre id="runSummary" style="white-space:pre-wrap;line-height:1.7" aria-live="polite"></pre>
22
  <p id="deadline"></p><p id="status" role="status">Ready. Inputs remain on this device until you run the test.</p>
23
  <details><summary>Effective training settings</summary><pre id="effectiveSettings"></pre></details><details><summary>Generation results</summary><pre id="generationHistory"></pre></details><details><summary>Star challenges — not evaluated</summary><p>The current runner has star-challenge reporting. Its evaluator and required statistics have not been ported to HF; no star result is inferred from a completed test.</p></details><h2>Selected track &amp; terrain</h2><div class="map" role="img" aria-label="Track map placeholder"><strong>Track map</strong><p>Renderer not connected yet.</p></div></section></div>
24
+ </div><section id="training" class="pane" hidden><div class="card"><h2>Training settings</h2><p class="hint">Choose the track on Drive & view. Choose the training settings and reward mix here, then start the run on Drive & view. Recipes and batch sequences are saved in this browser.</p><p><label for="trackPresetTraining">Training track</label><select id="trackPresetTraining" data-track-library disabled><option value="">Upload a custom track</option></select></p><p data-track-status role="status" class="hint">Loading built-in replica tracks…</p><div id="training_controls"><label for="training_ticks">Simulated ticks per generation</label><input id="training_ticks" type="number" min="1" max="18000" value="60"><small>60 ticks = one simulated second. Current preview limit: population × generations × ticks ≤ 4,000,000; execution timeout 25 seconds.</small>
25
  <div class="row"><div><label for="population">Population</label><input id="population" type="number" min="1" max="128" value="8" disabled><small>Population limits will follow the selected compute allocation.</small></div><div><label for="generations">Generations</label><input id="generations" type="number" min="1" max="1000" value="30" disabled><small>1–1,000; try 20–50 before review.</small></div></div>
26
  <label id="mutation_label" for="mutation">Mutation rate</label><input id="mutation" type="number" min="0" max="4.2" step="0.01" value="0.1" disabled><small>Mutation settings are passed to the upstream simulator.</small>
27
 
 
291
  message('Batch '+batch.slot+' loaded. Loading a batch does not start it.');
292
  });
293
  })();
294
+ </script><script>/* Read-only public reference library. No cookies or browser-persistent storage. */
295
+ (function(root,factory){
296
+ if(typeof module==='object'&&module.exports)module.exports=factory();
297
+ else root.TrackLibrary=factory();
298
+ })(typeof window==='undefined'?this:window,function(){
299
+ function create({fetch,digest,upload}){
300
+ let entries=[],selected='',cached=null;
301
+ return {
302
+ async load(){
303
+ const response=await fetch('/api/tracks',{cache:'no-store',credentials:'same-origin'});
304
+ if(!response.ok)throw Error('Built-in track catalog unavailable');
305
+ const catalog=await response.json();
306
+ if(!Array.isArray(catalog.tracks)||catalog.tracks.length>128)throw Error('Invalid track catalog');
307
+ const ids=new Set();
308
+ for(const entry of catalog.tracks){
309
+ if(!/^[a-z0-9-]{1,80}$/.test(entry.id)||ids.has(entry.id)||
310
+ typeof entry.display_name!=='string'||!entry.display_name.length||entry.display_name.length>100||
311
+ !Number.isInteger(entry.bytes)||entry.bytes<1||entry.bytes>1048576||
312
+ !/^[a-f0-9]{64}$/.test(entry.sha256))throw Error('Invalid track catalog');
313
+ ids.add(entry.id);
314
+ }
315
+ entries=catalog.tracks.map(entry=>({...entry}));
316
+ return this.entries();
317
+ },
318
+ entries:()=>entries.map(entry=>({...entry})),
319
+ selected:()=>selected,
320
+ select(id){
321
+ if(id&&!entries.some(entry=>entry.id===id))throw Error('Unknown built-in track');
322
+ if(id!==selected)cached=null;
323
+ selected=id;
324
+ },
325
+ info(){const entry=entries.find(entry=>entry.id===selected);return entry?{source:'builtin',...entry}:{source:'upload'};},
326
+ async file(){
327
+ if(!selected)return upload();
328
+ const entry=entries.find(entry=>entry.id===selected);
329
+ if(cached?.id===selected)return cached.blob;
330
+ const response=await fetch('/api/tracks/'+encodeURIComponent(selected)+'/file',
331
+ {cache:'no-store',credentials:'same-origin'});
332
+ if(!response.ok)throw Error('Built-in track unavailable; retry or choose an upload');
333
+ const bytes=await response.arrayBuffer();
334
+ if(bytes.byteLength!==entry.bytes||await digest(bytes)!==entry.sha256)
335
+ throw Error('Built-in track validation failed');
336
+ const blob=new Blob([bytes],{type:'application/octet-stream'});
337
+ cached={id:entry.id,blob};return blob;
338
+ }
339
+ };
340
+ }
341
+ function mount({document,fetch,digest}){
342
+ const selects=Array.from(document.querySelectorAll('[data-track-library]'));
343
+ const statuses=Array.from(document.querySelectorAll('[data-track-status]'));
344
+ const input=document.getElementById('track');
345
+ const picker=create({fetch,digest,upload:()=>input.files[0]});
346
+ let ready=false,busy=false;
347
+ function render(message){
348
+ for(const select of selects){select.value=picker.selected();select.disabled=busy||!ready;}
349
+ const info=picker.info();
350
+ for(const status of statuses)status.textContent=message??(info.source==='builtin'?
351
+ info.display_name+' selected. It remains selected after a run.':
352
+ 'Upload mode selected. Built-in replicas can be selected instead.');
353
+ }
354
+ for(const select of selects)select.addEventListener('change',()=>{
355
+ picker.select(select.value);if(select.value)input.value='';render();
356
+ });
357
+ input.addEventListener('change',()=>{picker.select('');render();});
358
+ picker.setBusy=value=>{busy=value;render();};
359
+ picker.load().then(()=>{
360
+ for(const select of selects){
361
+ for(const entry of picker.entries()){
362
+ const option=document.createElement('option');option.value=entry.id;
363
+ option.textContent=entry.display_name;select.append(option);
364
+ }
365
+ }
366
+ ready=picker.entries().length>0;
367
+ render(ready?undefined:'No built-in tracks in this installation. Custom uploads still work.');
368
+ }).catch(()=>render('Built-in catalog unavailable. Custom uploads still work.'));
369
+ return picker;
370
+ }
371
+ return {create,mount};
372
+ });
373
  </script><script src="/client.js"></script><script src="/hf-auth.js"></script><script>'use strict';
374
  // Navigation only. Editor and training/storage adapters are separate layers.
375
  document.querySelectorAll('[data-tab]').forEach(button=>button.addEventListener('click',()=>{
server.py CHANGED
@@ -10,12 +10,25 @@ from delivery import create_api, CapacityExceeded
10
  from worker import run_reported
11
  from training_config import validate_config
12
  from hf_identity import oauth_config
 
13
 
14
  ROOT=Path(__file__).resolve().parent
15
 
16
- def create_app(worker=run_reported,store=None,gpu_worker=None):
17
  app=create_api(store)
18
  admission=threading.BoundedSemaphore(1)
 
 
 
 
 
 
 
 
 
 
 
 
19
  @app.get('/api/auth/config')
20
  def auth_config():
21
  return JSONResponse(oauth_config(),headers={'Cache-Control':'no-store'})
 
10
  from worker import run_reported
11
  from training_config import validate_config
12
  from hf_identity import oauth_config
13
+ from builtin_tracks import TrackLibrary
14
 
15
  ROOT=Path(__file__).resolve().parent
16
 
17
+ def create_app(worker=run_reported,store=None,gpu_worker=None,track_library=None):
18
  app=create_api(store)
19
  admission=threading.BoundedSemaphore(1)
20
+ library=track_library if track_library is not None else TrackLibrary(ROOT/'builtin_tracks')
21
+ @app.get('/api/tracks')
22
+ def track_catalog():
23
+ return JSONResponse(library.catalog(),headers={'Cache-Control':'no-store'})
24
+ @app.get('/api/tracks/{identifier}/file')
25
+ def reference_track(identifier:str):
26
+ try:payload=library.read(identifier)
27
+ except KeyError:raise HTTPException(404,'Built-in track not found') from None
28
+ except (ValueError,OSError):raise HTTPException(503,'Built-in track validation failed') from None
29
+ return Response(payload,media_type='application/octet-stream',headers={'Cache-Control':'no-store'})
30
+ @app.get('/track-library.js')
31
+ def track_script():return FileResponse(ROOT/'track-library.js',media_type='text/javascript')
32
  @app.get('/api/auth/config')
33
  def auth_config():
34
  return JSONResponse(oauth_config(),headers={'Cache-Control':'no-store'})
track-library.js ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Read-only public reference library. No cookies or browser-persistent storage. */
2
+ (function(root,factory){
3
+ if(typeof module==='object'&&module.exports)module.exports=factory();
4
+ else root.TrackLibrary=factory();
5
+ })(typeof window==='undefined'?this:window,function(){
6
+ function create({fetch,digest,upload}){
7
+ let entries=[],selected='',cached=null;
8
+ return {
9
+ async load(){
10
+ const response=await fetch('/api/tracks',{cache:'no-store',credentials:'same-origin'});
11
+ if(!response.ok)throw Error('Built-in track catalog unavailable');
12
+ const catalog=await response.json();
13
+ if(!Array.isArray(catalog.tracks)||catalog.tracks.length>128)throw Error('Invalid track catalog');
14
+ const ids=new Set();
15
+ for(const entry of catalog.tracks){
16
+ if(!/^[a-z0-9-]{1,80}$/.test(entry.id)||ids.has(entry.id)||
17
+ typeof entry.display_name!=='string'||!entry.display_name.length||entry.display_name.length>100||
18
+ !Number.isInteger(entry.bytes)||entry.bytes<1||entry.bytes>1048576||
19
+ !/^[a-f0-9]{64}$/.test(entry.sha256))throw Error('Invalid track catalog');
20
+ ids.add(entry.id);
21
+ }
22
+ entries=catalog.tracks.map(entry=>({...entry}));
23
+ return this.entries();
24
+ },
25
+ entries:()=>entries.map(entry=>({...entry})),
26
+ selected:()=>selected,
27
+ select(id){
28
+ if(id&&!entries.some(entry=>entry.id===id))throw Error('Unknown built-in track');
29
+ if(id!==selected)cached=null;
30
+ selected=id;
31
+ },
32
+ info(){const entry=entries.find(entry=>entry.id===selected);return entry?{source:'builtin',...entry}:{source:'upload'};},
33
+ async file(){
34
+ if(!selected)return upload();
35
+ const entry=entries.find(entry=>entry.id===selected);
36
+ if(cached?.id===selected)return cached.blob;
37
+ const response=await fetch('/api/tracks/'+encodeURIComponent(selected)+'/file',
38
+ {cache:'no-store',credentials:'same-origin'});
39
+ if(!response.ok)throw Error('Built-in track unavailable; retry or choose an upload');
40
+ const bytes=await response.arrayBuffer();
41
+ if(bytes.byteLength!==entry.bytes||await digest(bytes)!==entry.sha256)
42
+ throw Error('Built-in track validation failed');
43
+ const blob=new Blob([bytes],{type:'application/octet-stream'});
44
+ cached={id:entry.id,blob};return blob;
45
+ }
46
+ };
47
+ }
48
+ function mount({document,fetch,digest}){
49
+ const selects=Array.from(document.querySelectorAll('[data-track-library]'));
50
+ const statuses=Array.from(document.querySelectorAll('[data-track-status]'));
51
+ const input=document.getElementById('track');
52
+ const picker=create({fetch,digest,upload:()=>input.files[0]});
53
+ let ready=false,busy=false;
54
+ function render(message){
55
+ for(const select of selects){select.value=picker.selected();select.disabled=busy||!ready;}
56
+ const info=picker.info();
57
+ for(const status of statuses)status.textContent=message??(info.source==='builtin'?
58
+ info.display_name+' selected. It remains selected after a run.':
59
+ 'Upload mode selected. Built-in replicas can be selected instead.');
60
+ }
61
+ for(const select of selects)select.addEventListener('change',()=>{
62
+ picker.select(select.value);if(select.value)input.value='';render();
63
+ });
64
+ input.addEventListener('change',()=>{picker.select('');render();});
65
+ picker.setBusy=value=>{busy=value;render();};
66
+ picker.load().then(()=>{
67
+ for(const select of selects){
68
+ for(const entry of picker.entries()){
69
+ const option=document.createElement('option');option.value=entry.id;
70
+ option.textContent=entry.display_name;select.append(option);
71
+ }
72
+ }
73
+ ready=picker.entries().length>0;
74
+ render(ready?undefined:'No built-in tracks in this installation. Custom uploads still work.');
75
+ }).catch(()=>render('Built-in catalog unavailable. Custom uploads still work.'));
76
+ return picker;
77
+ }
78
+ return {create,mount};
79
+ });