freesolo-flash-dev 1.2.52__tar.gz → 1.2.58__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (577) hide show
  1. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/CHANGELOG.md +28 -0
  2. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/PKG-INFO +1 -1
  3. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/core/spec.py +4 -23
  4. freesolo_flash_dev-1.2.58/flash/core/spec_persistence.py +123 -0
  5. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/cost/analytical.py +86 -35
  6. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/cost/spec.py +5 -0
  7. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/cost/types.py +24 -0
  8. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/io/heartbeat.py +41 -0
  9. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/perf/__init__.py +3 -3
  10. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/envs/identity.py +5 -1
  11. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/envs/loader.py +5 -1
  12. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/_lifecycle/bootstrap.py +21 -5
  13. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/_lifecycle/bootstrap_console.py +9 -5
  14. freesolo_flash_dev-1.2.58/flash/providers/_lifecycle/host/__init__.py +5 -0
  15. freesolo_flash_dev-1.2.58/flash/providers/_lifecycle/host/deadline_sleep.py +63 -0
  16. freesolo_flash_dev-1.2.58/flash/providers/_lifecycle/host/failmark.py +89 -0
  17. freesolo_flash_dev-1.2.58/flash/providers/_lifecycle/host/hostlog.py +60 -0
  18. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/_lifecycle/instance.py +47 -228
  19. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/_lifecycle/worker.py +3 -56
  20. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/artifacts/preload_runpod.py +1 -2
  21. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/artifacts/weight_cache.py +0 -1
  22. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/lambda_/jobs/builders.py +2 -2
  23. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/runpod/job_execution.py +2 -12
  24. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/runpod/jobs.py +2 -39
  25. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/runpod/serverless/__init__.py +0 -3
  26. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/runpod/serverless/endpoints.py +1 -93
  27. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/vast/jobs/builders.py +21 -25
  28. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/runner/__init__.py +2 -13
  29. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/runner/costs.py +2 -44
  30. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/runner/preparation.py +8 -153
  31. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/runner/status.py +4 -35
  32. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/runner/submit.py +1 -19
  33. freesolo_flash_dev-1.2.58/flash/runtime_capsule/__init__.py +48 -0
  34. freesolo_flash_dev-1.2.58/flash/runtime_capsule/build.py +231 -0
  35. freesolo_flash_dev-1.2.58/flash/runtime_capsule/manifest.py +240 -0
  36. freesolo_flash_dev-1.2.58/flash/runtime_capsule/profiles.py +65 -0
  37. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/schema/__init__.py +2 -6
  38. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/serve/urls.py +1 -2
  39. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/server/platform/runtime.py +3 -34
  40. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/pyproject.toml +2 -2
  41. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/scripts/check_function_size.py +4 -3
  42. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_cancel_remote.py +3 -59
  43. freesolo_flash_dev-1.2.58/tests/test_console_upload.py +145 -0
  44. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_cost_estimate.py +6 -2
  45. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_env_rate_limit_resolve.py +26 -6
  46. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_flash_worker.py +129 -28
  47. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_instance_bootstrap_coverage.py +49 -5
  48. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_jobs.py +9 -47
  49. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_kernel_fingerprint.py +36 -23
  50. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_lambda_runner.py +171 -119
  51. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_provider_teardown_robustness.py +1 -1
  52. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_runmgmt.py +0 -66
  53. freesolo_flash_dev-1.2.58/tests/test_runtime_capsule.py +434 -0
  54. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_server_api.py +1 -7
  55. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_server_envs_coverage.py +0 -1
  56. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_spec_and_validation.py +89 -465
  57. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_spec_contract_bytes.py +0 -64
  58. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_vast_runner.py +128 -29
  59. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_warmstart_cross_repo.py +3 -6
  60. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_weight_cache.py +8 -5
  61. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_worker_image.py +0 -11
  62. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_worker_init_heartbeat.py +219 -17
  63. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_worker_stack.py +28 -40
  64. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/uv.lock +1 -1
  65. freesolo_flash_dev-1.2.52/flash/core/spec_persistence.py +0 -227
  66. freesolo_flash_dev-1.2.52/tests/test_console_upload.py +0 -89
  67. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/.dockerignore +0 -0
  68. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/.env.example +0 -0
  69. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/.github/CODEOWNERS +0 -0
  70. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  71. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  72. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  73. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  74. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/.github/dependabot.yml +0 -0
  75. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/.github/workflows/auto-rebake.yml +0 -0
  76. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/.github/workflows/bake-kernel-cache.yml +0 -0
  77. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/.github/workflows/ci.yml +0 -0
  78. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/.github/workflows/main-source-guard.yml +0 -0
  79. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/.github/workflows/notify-tests-repo.yml +0 -0
  80. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/.github/workflows/publish-dev.yml +0 -0
  81. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/.github/workflows/publish-image.yml +0 -0
  82. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/.github/workflows/publish.yml +0 -0
  83. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/.github/workflows/version-parity.yml +0 -0
  84. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/.github/workflows/worker-image.yml +0 -0
  85. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/.gitignore +0 -0
  86. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/CODE_OF_CONDUCT.md +0 -0
  87. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/CONTRIBUTING.md +0 -0
  88. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/Dockerfile +0 -0
  89. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/Dockerfile.worker +0 -0
  90. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/LICENSE +0 -0
  91. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/NOTICE +0 -0
  92. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/README.md +0 -0
  93. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/SECURITY.md +0 -0
  94. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/SELF_HOSTING.md +0 -0
  95. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/build/kernel_cache/.gitignore +0 -0
  96. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/build/kernel_cache/.keep +0 -0
  97. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/deploy/infisical/README.md +0 -0
  98. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/deploy/infisical/entrypoint.sh +0 -0
  99. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/docker/Dockerfile.kernelcache +0 -0
  100. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/docker/Dockerfile.kernelcache.relayer +0 -0
  101. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/docker/bake_kernel_cache.py +0 -0
  102. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/docker/bake_pod_entry.py +0 -0
  103. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/docker/extract_cudart_fix.py +0 -0
  104. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/docker/kernel_fingerprint.py +0 -0
  105. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/docker/make_rp_handler.py +0 -0
  106. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/__init__.py +0 -0
  107. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/_internal/__init__.py +0 -0
  108. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/_internal/channel.py +0 -0
  109. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/_internal/diagnostics.py +0 -0
  110. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/_internal/fileio.py +0 -0
  111. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/_internal/logging.py +0 -0
  112. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/_internal/paths.py +0 -0
  113. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/adapters/__init__.py +0 -0
  114. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/adapters/artifacts.py +0 -0
  115. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/adapters/fused_experts.py +0 -0
  116. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/adapters/lora_rank.py +0 -0
  117. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/cli/__init__.py +0 -0
  118. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/cli/__main__.py +0 -0
  119. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/cli/commands/__init__.py +0 -0
  120. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/cli/commands/deploy.py +0 -0
  121. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/cli/commands/env/__init__.py +0 -0
  122. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/cli/commands/env/episode.py +0 -0
  123. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/cli/commands/env/eval.py +0 -0
  124. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/cli/commands/env/eval_args.py +0 -0
  125. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/cli/commands/env/imports.py +0 -0
  126. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/cli/commands/env/list.py +0 -0
  127. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/cli/commands/env/push.py +0 -0
  128. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/cli/commands/env/retained.py +0 -0
  129. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/cli/commands/env/setup.py +0 -0
  130. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/cli/commands/env/test.py +0 -0
  131. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/cli/commands/env/test_evaluations.py +0 -0
  132. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/cli/commands/env/test_params.py +0 -0
  133. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/cli/commands/env/test_warnings.py +0 -0
  134. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/cli/commands/prompt_budget.py +0 -0
  135. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/cli/commands/traces.py +0 -0
  136. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/cli/commands/train_cost.py +0 -0
  137. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/cli/scaffold/TRAINING.md +0 -0
  138. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/cli/scaffold/__init__.py +0 -0
  139. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/cli/ui/__init__.py +0 -0
  140. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/cli/ui/cost.py +0 -0
  141. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/cli/ui/env_panels.py +0 -0
  142. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/cli/ui/heartbeat.py +0 -0
  143. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/cli/ui/render.py +0 -0
  144. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/cli/ui/tables.py +0 -0
  145. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/cli/ui/tty.py +0 -0
  146. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/client/__init__.py +0 -0
  147. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/client/config.py +0 -0
  148. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/client/freesolo_api.py +0 -0
  149. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/client/http.py +0 -0
  150. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/client/runtime_secrets.py +0 -0
  151. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/client/shapes.py +0 -0
  152. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/client/specs.py +0 -0
  153. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/client/streaming.py +0 -0
  154. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/content/__init__.py +0 -0
  155. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/content/multimodal.py +0 -0
  156. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/content/structured_outputs.py +0 -0
  157. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/content/thinking.py +0 -0
  158. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/core/__init__.py +0 -0
  159. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/core/catalog.py +0 -0
  160. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/cost/__init__.py +0 -0
  161. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/cost/facts.py +0 -0
  162. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/__init__.py +0 -0
  163. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/plan/__init__.py +0 -0
  164. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/plan/kv_sizing.py +0 -0
  165. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/plan/model_config_probe.py +0 -0
  166. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/plan/prompt_budget.py +0 -0
  167. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/plan/recipe.py +0 -0
  168. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/plan/steps.py +0 -0
  169. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/plan/vram.py +0 -0
  170. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/profiling/__init__.py +0 -0
  171. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/profiling/dataset_profile.py +0 -0
  172. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/profiling/reasoning_render.py +0 -0
  173. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/profiling/sft_workload.py +0 -0
  174. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/profiling/tokenizer.py +0 -0
  175. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/profiling/workload_profile.py +0 -0
  176. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/result/__init__.py +0 -0
  177. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/result/accounting.py +0 -0
  178. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/result/rollout_samples.py +0 -0
  179. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/__init__.py +0 -0
  180. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/__main__.py +0 -0
  181. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/backend_common.py +0 -0
  182. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/entry/__init__.py +0 -0
  183. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/entry/opd.py +0 -0
  184. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/entry/rl.py +0 -0
  185. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/entry/sft.py +0 -0
  186. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/io/__init__.py +0 -0
  187. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/io/hf.py +0 -0
  188. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/io/prefetch.py +0 -0
  189. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/io/wandb_log.py +0 -0
  190. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/model/__init__.py +0 -0
  191. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/model/adapter.py +0 -0
  192. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/model/chatml_mask.py +0 -0
  193. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/model/decoding.py +0 -0
  194. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/model/lora.py +0 -0
  195. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/model/packing.py +0 -0
  196. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/opd_train.py +0 -0
  197. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/opd_train_runner.py +0 -0
  198. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/perf/diagnostics.py +0 -0
  199. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/perf/lifecycle.py +0 -0
  200. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/perf/liger.py +0 -0
  201. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/perf/memory.py +0 -0
  202. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/rl_train.py +0 -0
  203. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/rl_train_runner.py +0 -0
  204. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/runtime/__init__.py +0 -0
  205. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/runtime/kernel_warmup.py +0 -0
  206. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/runtime/pkg_proxy.py +0 -0
  207. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/runtime/rng.py +0 -0
  208. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/score_batcher.py +0 -0
  209. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/sft_train.py +0 -0
  210. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/sft_train_runner.py +0 -0
  211. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/teacher/__init__.py +0 -0
  212. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/teacher/client.py +0 -0
  213. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/teacher/encoding.py +0 -0
  214. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/teacher/tokenizer_align.py +0 -0
  215. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/__init__.py +0 -0
  216. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/core/__init__.py +0 -0
  217. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/core/checkpoint_lifecycle.py +0 -0
  218. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/core/child/__init__.py +0 -0
  219. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/core/child/glue.py +0 -0
  220. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/core/child/runtime.py +0 -0
  221. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/core/step_timing.py +0 -0
  222. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/finalize.py +0 -0
  223. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/opd/__init__.py +0 -0
  224. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/opd/batching.py +0 -0
  225. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/opd/bridge.py +0 -0
  226. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/opd/child/__init__.py +0 -0
  227. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/opd/child/bridge.py +0 -0
  228. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/opd/child/entry.py +0 -0
  229. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/opd/child/multiturn.py +0 -0
  230. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/opd/child/plugin.py +0 -0
  231. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/opd/child/replay_guard.py +0 -0
  232. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/opd/child/runtime.py +0 -0
  233. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/opd/child/structured.py +0 -0
  234. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/opd/failures.py +0 -0
  235. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/opd/gkd.py +0 -0
  236. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/opd/multiturn_validation.py +0 -0
  237. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/opd/overrides.py +0 -0
  238. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/opd/prompts.py +0 -0
  239. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/opd/reporting.py +0 -0
  240. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/opd/scoring.py +0 -0
  241. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/opd/state.py +0 -0
  242. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/opd/validation.py +0 -0
  243. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/rl/__init__.py +0 -0
  244. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/rl/checkpoints.py +0 -0
  245. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/rl/child/__init__.py +0 -0
  246. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/rl/child/entry.py +0 -0
  247. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/rl/child/multiturn.py +0 -0
  248. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/rl/child/patches.py +0 -0
  249. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/rl/child/plugin.py +0 -0
  250. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/rl/config.py +0 -0
  251. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/rl/inputs.py +0 -0
  252. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/rl/multi_turn.py +0 -0
  253. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/rl/reward_module.py +0 -0
  254. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/rl/scoring.py +0 -0
  255. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/rl/single_turn.py +0 -0
  256. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/rl/verl_config.py +0 -0
  257. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/sft/__init__.py +0 -0
  258. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/sft/checkpoints.py +0 -0
  259. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/sft/child/entry.py +0 -0
  260. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/sft/child/plugin.py +0 -0
  261. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/sft/config.py +0 -0
  262. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/verl/__init__.py +0 -0
  263. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/verl/capabilities.py +0 -0
  264. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/verl/checkpoints.py +0 -0
  265. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/verl/child_io.py +0 -0
  266. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/verl/diagnostics.py +0 -0
  267. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/verl/parallelism.py +0 -0
  268. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker/verl/parent_work.py +0 -0
  269. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/engine/worker_entrypoint.py +0 -0
  270. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/envs/__init__.py +0 -0
  271. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/envs/adapter.py +0 -0
  272. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/envs/base.py +0 -0
  273. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/envs/cache_security.py +0 -0
  274. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/envs/dataset_selection.py +0 -0
  275. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/envs/evaluations.py +0 -0
  276. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/envs/namespace_listing.py +0 -0
  277. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/envs/package/__init__.py +0 -0
  278. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/envs/package/limits.py +0 -0
  279. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/envs/package/unpack.py +0 -0
  280. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/envs/pull.py +0 -0
  281. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/__init__.py +0 -0
  282. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/_lifecycle/__init__.py +0 -0
  283. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/_lifecycle/auth.py +0 -0
  284. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/_lifecycle/bootstrap_pip.py +0 -0
  285. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/_lifecycle/bootstrap_secrets.py +0 -0
  286. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/_lifecycle/deadline.py +0 -0
  287. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/_lifecycle/http.py +0 -0
  288. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/_lifecycle/poll.py +0 -0
  289. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/_lifecycle/poll_instance.py +0 -0
  290. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/_lifecycle/provider.py +0 -0
  291. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/_lifecycle/terminal_artifacts.py +0 -0
  292. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/allocator.py +0 -0
  293. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/artifacts/__init__.py +0 -0
  294. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/artifacts/hf.py +0 -0
  295. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/base.py +0 -0
  296. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/fit_errors.py +0 -0
  297. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/lambda_/__init__.py +0 -0
  298. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/lambda_/api.py +0 -0
  299. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/lambda_/auth.py +0 -0
  300. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/lambda_/gpus.py +0 -0
  301. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/lambda_/jobs/__init__.py +0 -0
  302. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/lambda_/jobs/reap.py +0 -0
  303. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/lambda_/preflight.py +0 -0
  304. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/lambda_/pricing.py +0 -0
  305. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/preflight.py +0 -0
  306. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/realized.py +0 -0
  307. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/runpod/__init__.py +0 -0
  308. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/runpod/api.py +0 -0
  309. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/runpod/auth.py +0 -0
  310. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/runpod/cost.py +0 -0
  311. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/runpod/gpus.py +0 -0
  312. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/runpod/preflight.py +0 -0
  313. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/runpod/pricing.py +0 -0
  314. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/runpod/resources.py +0 -0
  315. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/sharding.py +0 -0
  316. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/vast/__init__.py +0 -0
  317. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/vast/api.py +0 -0
  318. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/vast/auth.py +0 -0
  319. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/vast/jobs/__init__.py +0 -0
  320. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/vast/preflight.py +0 -0
  321. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/providers/vast/pricing.py +0 -0
  322. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/py.typed +0 -0
  323. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/runner/artifacts.py +0 -0
  324. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/runner/attempts.py +0 -0
  325. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/runner/deadlines.py +0 -0
  326. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/runner/reconciliation.py +0 -0
  327. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/runner/results/__init__.py +0 -0
  328. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/runner/results/checkpoints.py +0 -0
  329. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/runner/results/verified_revisions.py +0 -0
  330. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/runner/supervise/__init__.py +0 -0
  331. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/runner/supervise/attach.py +0 -0
  332. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/runner/supervise/deploy.py +0 -0
  333. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/runner/supervise/lifecycle.py +0 -0
  334. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/runner/supervise/recovery.py +0 -0
  335. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/runner/supervise/retry_decision.py +0 -0
  336. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/runner/supervise/seed_submission.py +0 -0
  337. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/runner/supervise/transitions.py +0 -0
  338. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/runner/weight_cache.py +0 -0
  339. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/schema/fields.py +0 -0
  340. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/serve/__init__.py +0 -0
  341. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/serve/adapter_check.py +0 -0
  342. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/serve/deploy.py +0 -0
  343. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/serve/errors.py +0 -0
  344. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/serve/export.py +0 -0
  345. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/serve/preflight.py +0 -0
  346. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/serve/responses.py +0 -0
  347. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/serve/streaming.py +0 -0
  348. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/serve/thinking.py +0 -0
  349. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/server/__init__.py +0 -0
  350. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/server/__main__.py +0 -0
  351. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/server/app.py +0 -0
  352. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/server/billing/__init__.py +0 -0
  353. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/server/billing/charges.py +0 -0
  354. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/server/billing/retry.py +0 -0
  355. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/server/domain/__init__.py +0 -0
  356. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/server/domain/checkpoints.py +0 -0
  357. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/server/domain/environment_registry.py +0 -0
  358. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/server/domain/envs.py +0 -0
  359. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/server/domain/projects.py +0 -0
  360. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/server/domain/reconcile.py +0 -0
  361. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/server/domain/repo_cleanup.py +0 -0
  362. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/server/domain/run_registry.py +0 -0
  363. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/server/domain/teacher_broker.py +0 -0
  364. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/server/domain/teacher_errors.py +0 -0
  365. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/server/domain/teacher_requests.py +0 -0
  366. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/server/platform/__init__.py +0 -0
  367. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/server/platform/auth.py +0 -0
  368. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/server/platform/db.py +0 -0
  369. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/server/platform/deps.py +0 -0
  370. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/server/platform/internal_client.py +0 -0
  371. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/server/platform/locks.py +0 -0
  372. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/server/routes/__init__.py +0 -0
  373. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/server/routes/envs.py +0 -0
  374. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/server/routes/meta.py +0 -0
  375. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/server/routes/runs.py +0 -0
  376. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/server/routes/serving.py +0 -0
  377. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/server/routes/serving_completion.py +0 -0
  378. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/server/routes/serving_revisions.py +0 -0
  379. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/server/routes/serving_smoke.py +0 -0
  380. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/server/routes/teacher.py +0 -0
  381. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/teacher/__init__.py +0 -0
  382. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/teacher/limits.py +0 -0
  383. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/flash/teacher/retry_contract.py +0 -0
  384. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/scripts/build_dev_dist.py +0 -0
  385. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/scripts/check_file_size.py +0 -0
  386. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/scripts/check_verl_pin_exists.py +0 -0
  387. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/scripts/scrub_history.sh +0 -0
  388. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/__init__.py +0 -0
  389. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/_helpers/__init__.py +0 -0
  390. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/_helpers/profile.py +0 -0
  391. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/_helpers/runner.py +0 -0
  392. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/_helpers/specs.py +0 -0
  393. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/_helpers/teacher.py +0 -0
  394. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/_helpers/vast.py +0 -0
  395. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/conftest.py +0 -0
  396. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/fixtures/math_eval.jsonl +0 -0
  397. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/fixtures/math_train.jsonl +0 -0
  398. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/live/__init__.py +0 -0
  399. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/live/conftest.py +0 -0
  400. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/live/test_lambda_live.py +0 -0
  401. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/live/test_runpod_live.py +0 -0
  402. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/live/test_sft_thinking_render_live.py +0 -0
  403. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/live/test_vast_live.py +0 -0
  404. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_accounting_coverage.py +0 -0
  405. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_adapter_shard_completeness.py +0 -0
  406. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_agent_flash_cli_contract.py +0 -0
  407. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_algorithms.py +0 -0
  408. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_allocator.py +0 -0
  409. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_backend_common.py +0 -0
  410. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_backend_jobspec_contract.py +0 -0
  411. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_bake_kernel_cache.py +0 -0
  412. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_base_model_provenance.py +0 -0
  413. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_billing_retry.py +0 -0
  414. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_build_context_contract.py +0 -0
  415. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_catalog_consistency.py +0 -0
  416. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_catalog_only_models.py +0 -0
  417. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_charge_pricing.py +0 -0
  418. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_checkpoint_lifecycle.py +0 -0
  419. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_checkpoints.py +0 -0
  420. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_cli_commands.py +0 -0
  421. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_cli_commands_coverage.py +0 -0
  422. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_cli_credential_shadowing.py +0 -0
  423. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_cli_errors.py +0 -0
  424. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_cli_estimate.py +0 -0
  425. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_cli_gpus_flag.py +0 -0
  426. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_cli_help.py +0 -0
  427. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_cli_main_coverage.py +0 -0
  428. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_cli_managed.py +0 -0
  429. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_cli_render_coverage.py +0 -0
  430. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_cli_render_theme.py +0 -0
  431. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_cli_traces.py +0 -0
  432. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_cli_wandb_warning.py +0 -0
  433. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_client.py +0 -0
  434. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_client_import_purity.py +0 -0
  435. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_client_server_integration.py +0 -0
  436. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_client_stream_reads.py +0 -0
  437. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_config_env_vars.py +0 -0
  438. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_config_overrides.py +0 -0
  439. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_controlled_experiment_repairs.py +0 -0
  440. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_cost_analytical.py +0 -0
  441. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_cost_equation.py +0 -0
  442. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_cost_hardware.py +0 -0
  443. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_cost_models.py +0 -0
  444. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_dataset_profile.py +0 -0
  445. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_deploy_alias_move_warning.py +0 -0
  446. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_deploy_latency.py +0 -0
  447. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_dev_channel.py +0 -0
  448. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_disk_gb.py +0 -0
  449. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_endpoint_name.py +0 -0
  450. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_env_cache_evict.py +0 -0
  451. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_env_delete.py +0 -0
  452. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_env_download.py +0 -0
  453. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_env_download_api.py +0 -0
  454. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_env_evaluations.py +0 -0
  455. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_env_list_api.py +0 -0
  456. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_env_list_cli.py +0 -0
  457. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_env_list_hub.py +0 -0
  458. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_env_no_install.py +0 -0
  459. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_env_publish.py +0 -0
  460. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_env_pull.py +0 -0
  461. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_env_pull_coverage.py +0 -0
  462. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_env_pull_loader_coverage.py +0 -0
  463. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_env_pull_managed_control_plane.py +0 -0
  464. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_env_push.py +0 -0
  465. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_env_ref_pinning.py +0 -0
  466. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_env_test.py +0 -0
  467. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_envs_coverage.py +0 -0
  468. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_export.py +0 -0
  469. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_flash_mvp.py +0 -0
  470. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_flashinfer_cache_dirs.py +0 -0
  471. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_freesolo_api_transport.py +0 -0
  472. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_fused_expert_warmstart.py +0 -0
  473. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_github_urlopen_retry.py +0 -0
  474. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_gpu_type_single_field.py +0 -0
  475. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_gpus.py +0 -0
  476. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_grpo_params.py +0 -0
  477. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_grpo_resident_sizing.py +0 -0
  478. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_grpo_reward_batching.py +0 -0
  479. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_health_liveness.py +0 -0
  480. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_hf_retry.py +0 -0
  481. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_idle_endpoint_reaper.py +0 -0
  482. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_infisical_secrets.py +0 -0
  483. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_internal_client.py +0 -0
  484. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_kernel_cache.py +0 -0
  485. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_kv_util.py +0 -0
  486. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_lambda_api_coverage.py +0 -0
  487. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_logging.py +0 -0
  488. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_login_perms.py +0 -0
  489. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_lora_rank_coverage.py +0 -0
  490. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_lora_rank_preflight.py +0 -0
  491. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_managed_config_fields.py +0 -0
  492. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_managed_hf_repo.py +0 -0
  493. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_metrics_schema_agent_contract.py +0 -0
  494. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_mig_guard.py +0 -0
  495. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_multi_gpu_gate.py +0 -0
  496. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_multimodal_training.py +0 -0
  497. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_named_reward_metrics.py +0 -0
  498. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_oom_escalate_gpu.py +0 -0
  499. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_opd.py +0 -0
  500. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_opd_limits.py +0 -0
  501. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_opd_multiturn_eos_boundary.py +0 -0
  502. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_opd_multiturn_failure_exit.py +0 -0
  503. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_opd_replay_guard.py +0 -0
  504. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_opd_resume_safety.py +0 -0
  505. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_opd_train.py +0 -0
  506. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_orchestrator_flash.py +0 -0
  507. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_packing.py +0 -0
  508. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_packing_coverage.py +0 -0
  509. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_parasail_teacher.py +0 -0
  510. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_poll_helpers.py +0 -0
  511. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_preflight.py +0 -0
  512. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_projects.py +0 -0
  513. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_prompt_budget.py +0 -0
  514. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_provider_preflight_coverage.py +0 -0
  515. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_provider_routing.py +0 -0
  516. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_providers_symmetry.py +0 -0
  517. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_realized_cost.py +0 -0
  518. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_repo_cleanup.py +0 -0
  519. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_resolve_params_b.py +0 -0
  520. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_resume_on_retry.py +0 -0
  521. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_rl_train.py +0 -0
  522. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_rollout_samples.py +0 -0
  523. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_runpod_api_delete.py +0 -0
  524. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_runpod_key_fingerprint.py +0 -0
  525. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_runpod_key_waterfall.py +0 -0
  526. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_serve.py +0 -0
  527. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_serve_reasoning_content.py +0 -0
  528. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_server_app_coverage.py +0 -0
  529. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_server_auth_singleflight.py +0 -0
  530. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_server_billing.py +0 -0
  531. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_server_checkpoints_coverage.py +0 -0
  532. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_server_db.py +0 -0
  533. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_server_locks_coverage.py +0 -0
  534. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_server_standalone.py +0 -0
  535. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_serving_context_preflight.py +0 -0
  536. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_serving_contract.py +0 -0
  537. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_serving_schema_coverage.py +0 -0
  538. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_sft_chunked_nll.py +0 -0
  539. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_sft_example_selection.py +0 -0
  540. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_sft_gc_off.py +0 -0
  541. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_sft_max_context.py +0 -0
  542. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_sft_startup_block.py +0 -0
  543. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_sft_train.py +0 -0
  544. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_sft_workload.py +0 -0
  545. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_step_floor.py +0 -0
  546. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_step_metrics.py +0 -0
  547. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_step_timing.py +0 -0
  548. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_structured_outputs.py +0 -0
  549. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_teacher_broker.py +0 -0
  550. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_teacher_encoding_contract.py +0 -0
  551. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_terminal_artifacts.py +0 -0
  552. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_thinking_config.py +0 -0
  553. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_train_context_preflight.py +0 -0
  554. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_training_controls.py +0 -0
  555. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_type_comment_prose.py +0 -0
  556. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_vast_api.py +0 -0
  557. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_vast_api_coverage.py +0 -0
  558. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_vast_offers.py +0 -0
  559. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_vast_provider_coverage.py +0 -0
  560. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_verified_revisions.py +0 -0
  561. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_verifiers.py +0 -0
  562. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_verl_checkpoint_export.py +0 -0
  563. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_verl_child_plugins.py +0 -0
  564. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_verl_silence_watchdog.py +0 -0
  565. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_version.py +0 -0
  566. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_vl_warmstart_adapter_keys.py +0 -0
  567. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_vram_architecture.py +0 -0
  568. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_wandb_link.py +0 -0
  569. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_wandb_naming.py +0 -0
  570. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_warmstart_adapter_download.py +0 -0
  571. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_warmstart_error_attribution.py +0 -0
  572. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_worker_dryrun.py +0 -0
  573. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_worker_hardexit.py +0 -0
  574. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_worker_thinking.py +0 -0
  575. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_workflow_contracts.py +0 -0
  576. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_workload_profile.py +0 -0
  577. {freesolo_flash_dev-1.2.52 → freesolo_flash_dev-1.2.58}/tests/test_zero2_sharding_gate.py +0 -0
@@ -39,6 +39,34 @@ This file starts at 1.1.35. Earlier releases are not reconstructed here; use
39
39
 
40
40
  ### Fixed
41
41
 
42
+ - An ordered `[gpu] type` list is now priced over every class it declares acceptable, not just the
43
+ first. Allocation cost-ranks the whole set, so quoting the head alone priced a shape the run may
44
+ never be given — an authored `["B200", "H100"]` quoted roughly 3x the H100 the allocator would
45
+ really rent, and the submit-time affordability check runs on that estimate, so a run the
46
+ organization could afford could be refused before allocation ever got to choose. A single
47
+ authored class is still a hard pin, and a no-fit rejection now names every acceptable class
48
+ rather than whichever happened to be written first.
49
+
50
+ - A provider preference that exhausts every configured provider no longer falls back to quoting
51
+ hardware this plane cannot rent. The final fallback dropped the restriction and ranked the
52
+ registered RunPod pool regardless of credentials, so a vast-only plane could quote a B200: the
53
+ estimate passed affordability and the run was recorded, only for live allocation to fail. The
54
+ quote now raises against the eligible set, which names the real constraint.
55
+
56
+ - A GitHub token that is invalid, expired, or missing a scope now fails during preparation instead
57
+ of after a GPU is rented. Non-rate-limit 401 and 403 responses were left as untyped errors, which
58
+ the submit-time preflight treats as a transient blip worth deferring, so the run proceeded
59
+ through affordability and allocation and hit the same permanent credential error on the worker.
60
+ They are now classified permanent, like 404 and 422. The rate-limit 403 is still transient.
61
+
62
+ - A slow heartbeat upload no longer stalls every other heartbeat behind it. The throttle clock only
63
+ advances once a commit lands, so during a slow HuggingFace commit other callers still saw an
64
+ upload as due and blocked on the upload lock for up to its acquire timeout — 30s, or 120s on a
65
+ critical stage — which stalled the liveness daemon and delayed leaving the wrapped stage by the
66
+ same window. A throttled heartbeat now skips while a commit is in flight, since that commit
67
+ already carries the stage's state. Terminal, error, initial, and forced step commits still queue
68
+ and land: they carry state no later heartbeat would repair.
69
+
42
70
  - A GRPO or OPD run whose rollout actor exited hard no longer wedges on a paid GPU until the
43
71
  wall-time limit. The actor's `os._exit` bypassed verl's own prompt handler, so the prompt
44
72
  stayed `running` forever and verl's unbounded replay poll waited on it at ~0% utilization. The
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: freesolo-flash-dev
3
- Version: 1.2.52
3
+ Version: 1.2.58
4
4
  Summary: Flash — managed LoRA post-training (SFT/GRPO/OPD) for Freesolo environments, driven by the `flash` CLI
5
5
  Project-URL: Homepage, https://github.com/freesolo-co/flash
6
6
  Project-URL: Repository, https://github.com/freesolo-co/flash
@@ -27,19 +27,7 @@ from uuid import UUID
27
27
 
28
28
  from flash._internal.diagnostics import SECRET_ENV_KEYS_ENV
29
29
  from flash.core.catalog import DEFAULT_MODEL, normalize_algorithm
30
-
31
- # `DROPPED_TOP_LEVEL_KEYS` keeps its historical private alias rather than being renamed at its 5 call
32
- # sites: `flash.runner` re-exports it as a package attribute and `preparation.py` reads it back through
33
- # `_runner()`, which is the seam the tests patch. Renaming it is a separate change from moving it, and
34
- # doing both at once would put a live recovery path's patch points inside a refactor whose whole claim
35
- # is that nothing behavioral moved.
36
- from flash.core.spec_persistence import (
37
- DROPPED_TOP_LEVEL_KEYS as _DROPPED_TOP_LEVEL_KEYS,
38
- )
39
30
  from flash.core.spec_persistence import (
40
- REMOVED_PERSISTED_TRAIN_KEYS,
41
- announce_dropped_keys,
42
- migrated_optimizer_batch,
43
31
  opt_float,
44
32
  opt_int,
45
33
  str_tuple,
@@ -654,10 +642,9 @@ class JobSpec:
654
642
  if not isinstance(data, dict):
655
643
  raise TypeError("job spec must be an object")
656
644
  allowed_top_level = {item.name for item in fields(cls)}
657
- unknown_top_level = sorted(set(data) - allowed_top_level - _DROPPED_TOP_LEVEL_KEYS)
645
+ unknown_top_level = sorted(set(data) - allowed_top_level)
658
646
  if unknown_top_level:
659
647
  raise ValueError(f"job spec has unknown key(s): {', '.join(unknown_top_level)}")
660
- announce_dropped_keys(data)
661
648
  env = data.get("environment") or {}
662
649
  # Reject stale payloads carrying a local `path`; worker only runs published env ids.
663
650
  if isinstance(env, dict) and env.get("path"):
@@ -665,12 +652,7 @@ class JobSpec:
665
652
  "local environment paths are no longer supported; the worker only runs "
666
653
  "published Freesolo environment ids"
667
654
  )
668
- train = validated_section(
669
- data,
670
- "train",
671
- {item.name for item in fields(TrainSpec)},
672
- removed=REMOVED_PERSISTED_TRAIN_KEYS,
673
- )
655
+ train = validated_section(data, "train", {item.name for item in fields(TrainSpec)})
674
656
  gpu = validated_section(data, "gpu", {item.name for item in fields(GpuSpec)})
675
657
  gpu_type, gpu_type_fallbacks = _parse_persisted_gpu_types(gpu)
676
658
  provider, providers = validated_persisted_providers(gpu, gpu_type, gpu_type_fallbacks)
@@ -679,9 +661,8 @@ class JobSpec:
679
661
  raise TypeError("project must be a string")
680
662
  project = require_project_id(project_raw) if project_raw.strip() else ""
681
663
  algorithm = normalize_algorithm(data.get("algorithm", cls.algorithm))
682
- # one reading of the optimizer batch for both keys: the rollout spelling changed in 1.1.43
683
- # and a persisted spec can still carry the old one.
684
- batch_size, prompts_per_step = migrated_optimizer_batch(train, algorithm)
664
+ batch_size = opt_int(train.get("batch_size"))
665
+ prompts_per_step = opt_int(train.get("prompts_per_step"))
685
666
  return cls(
686
667
  model=data.get("model", cls.model),
687
668
  model_revision=_model_revision(data.get("model_revision", cls.model_revision)),
@@ -0,0 +1,123 @@
1
+ """Decoding rules for PERSISTED job-spec records, as distinct from authored configuration.
2
+
3
+ `JobSpec` serves four different contracts, and this module owns exactly one of them: reading back
4
+ bytes that were already written to `~/.flash/runs/<run_id>.json`. That is not the same job as
5
+ validating a config a user just wrote, and the two must not be confused:
6
+
7
+ - authored configuration is parsed by `flash.schema.spec_from_dict`, which is STRICT. an unknown key
8
+ is a typo in a file the author can still fix, so it fails loudly.
9
+ - a persisted record is parsed by `JobSpec.from_dict`, which applies the looser scalar coercions
10
+ here. It reads a record this build wrote, in this build's shape; an unknown key is fatal in both.
11
+
12
+ Serialized-byte warning: `flash/runner/preparation.py::_preparation_digest` sha256-hashes the
13
+ canonical JSON of `to_dict()` and `to_internal_dict()` output. Key ORDER is safe there
14
+ (`sort_keys=True`), but key PRESENCE is not -- adding, dropping, or renaming a key in a decode path
15
+ changes the digest and fails integrity validation for a run whose snapshot was already written.
16
+
17
+ These functions take plain dicts and return plain dicts and scalars. That is the rule that keeps the
18
+ module importable by `spec.py` rather than the other way round, and it is why `validated_section`
19
+ takes its allowed-key set as an argument instead of reading `fields(TrainSpec)` itself.
20
+
21
+ What is deliberately NOT here: `_coerce_wandb` and `_parse_persisted_gpu_types` are also called only
22
+ from `JobSpec.from_dict`, so they belong to this contract by usage -- but they construct `WandbSpec`
23
+ and reach `_validated_gpu_type`, which `__post_init__` needs too. Moving them would make this module
24
+ import the dataclasses that import it. The boundary is therefore drawn at "persisted-decoding logic
25
+ that does not depend on the spec types themselves".
26
+ """
27
+
28
+ from __future__ import annotations
29
+
30
+ from typing import Any
31
+
32
+
33
+ def validated_section(data: dict[str, Any], name: str, allowed: set[str]) -> dict[str, Any]:
34
+ """Read one nested block (``[train]``, ``[gpu]``) of a persisted record, rejecting unknown keys.
35
+
36
+ A missing block and an explicit null are the same state -- both mean "authored nothing" -- so both
37
+ normalize to empty rather than one of them raising. An unknown key is fatal.
38
+ """
39
+ section = data.get(name)
40
+ if section is None:
41
+ section = {}
42
+ if not isinstance(section, dict):
43
+ raise TypeError(f"{name} must be an object")
44
+ unknown = sorted(set(section) - allowed)
45
+ if unknown:
46
+ raise ValueError(f"{name} has unknown key(s): {', '.join(unknown)}")
47
+ return section
48
+
49
+
50
+ def validated_persisted_providers(
51
+ gpu: dict[str, Any], gpu_type: str, gpu_type_fallbacks: tuple[str, ...]
52
+ ) -> tuple[str, tuple[str, ...]]:
53
+ """``(provider, providers)`` from a persisted ``[gpu]`` block, cross-checked against its classes.
54
+
55
+ ``GpuSpec.__post_init__`` runs the same both-set check but cannot replace this one: ``allow_empty``
56
+ here keys off whether the record CARRIED a ``providers`` key, and that presence is exactly what the
57
+ dataclass has already lost by the time it validates. An explicitly empty preference and an absent
58
+ one are different states in a stored record.
59
+ """
60
+ from flash.providers import PROVIDER_NAMES, validated_provider_preferences
61
+
62
+ provider = gpu.get("provider", "")
63
+ if not isinstance(provider, str):
64
+ raise TypeError("gpu.provider must be a string")
65
+ provider = provider.strip().lower()
66
+ providers = validated_provider_preferences(
67
+ gpu.get("providers", ()), allow_empty="providers" not in gpu
68
+ )
69
+ if provider and providers:
70
+ raise ValueError("gpu.provider and gpu.providers cannot both be set")
71
+ if provider or providers or gpu_type:
72
+ from flash.providers.base import providers_for
73
+
74
+ if provider and provider not in PROVIDER_NAMES:
75
+ raise ValueError(f"unknown gpu.provider {provider!r}")
76
+ # a hard provider pin must carry every acceptable class. provider preferences stay soft: an
77
+ # ineligible named provider contributes no candidate, while eligible named or unnamed
78
+ # configured providers remain available for failover.
79
+ for candidate in (gpu_type, *gpu_type_fallbacks):
80
+ if candidate and provider and provider not in providers_for(candidate):
81
+ raise ValueError(
82
+ f"gpu.provider {provider!r} cannot provision gpu.type {candidate!r}"
83
+ )
84
+ return provider, providers
85
+
86
+
87
+ def str_tuple(value: Any) -> tuple[str, ...]:
88
+ """Normalize a string-or-list knob to a tuple of strings; a bare string is one element, not iterated."""
89
+ if value is None:
90
+ return ()
91
+ if isinstance(value, str):
92
+ return (value,) if value else ()
93
+ return tuple(s for s in (str(x) for x in value) if s)
94
+
95
+
96
+ def volume_gb(value: Any, default: int = 100) -> int:
97
+ """Parse volume size in GB; non-positive / non-numeric / missing values return default."""
98
+ if isinstance(value, bool):
99
+ # bool is an int subclass; reject to avoid int(True)==1 becoming a 1 GB volume.
100
+ return default
101
+ try:
102
+ gb = int(value)
103
+ except (TypeError, ValueError):
104
+ return default
105
+ return gb if gb > 0 else default
106
+
107
+
108
+ def opt_int(value: Any) -> int | None:
109
+ """Parse optional int; rejects bools (bool is int subclass — int(True)==1 is a footgun)."""
110
+ if value is None:
111
+ return None
112
+ if isinstance(value, bool):
113
+ raise TypeError(f"expected a number, got bool {value!r}")
114
+ return int(value)
115
+
116
+
117
+ def opt_float(value: Any) -> float | None:
118
+ """Parse optional float; rejects bools (mirrors ``opt_int``)."""
119
+ if value is None:
120
+ return None
121
+ if isinstance(value, bool):
122
+ raise TypeError(f"expected a number, got bool {value!r}")
123
+ return float(value)
@@ -597,7 +597,15 @@ def _offline_preferred_gpu_shape(config: RunConfig) -> tuple[str, int, int, str,
597
597
  quote[4] * quote[2] * sharded_step_seconds(config, quote[0], quote[2], quote[3])
598
598
  ),
599
599
  )
600
- # preserve the existing unpinned diagnostic when no registered provider has a structural fit.
600
+ # every eligible provider has now been tried and none has a structural fit. dropping the
601
+ # restriction here to reach the unpinned `provider="auto"` diagnostic would rank the registered
602
+ # runpod pool regardless of credentials, quoting a shape this plane cannot rent -- the same
603
+ # defect the eligibility filter above exists to prevent, reintroduced at the last step. that
604
+ # quote would then pass affordability and only fail once live allocation runs, after the run is
605
+ # recorded. re-raise the eligible set's own failure instead, which names the real constraint.
606
+ if eligible:
607
+ return _offline_gpu_shape(replace(config, provider=eligible[0], providers=()))
608
+ # no provider is registered at all (an empty registry): keep the historical unpinned answer.
601
609
  return _offline_gpu_shape(replace(config, providers=()))
602
610
 
603
611
 
@@ -629,11 +637,18 @@ def _offline_gpu_shape(config: RunConfig) -> tuple[str, int, int, str, float]:
629
637
  providers_for,
630
638
  rentable_gpu_counts,
631
639
  )
632
- from flash.providers.fit_errors import vram_fit_error_message, vram_knob_advice
633
640
 
634
641
  provider = config.provider if config.provider != "auto" else "auto"
635
642
  if config.gpu_type:
636
- names = (canonical_gpu(config.gpu_type),)
643
+ # rank every class the author declared acceptable, not just the head. `allocate()` cost-ranks
644
+ # the whole ordered set, so quoting the head alone prices a shape the run may never be given
645
+ # -- an authored ["B200", "H100"] quotes 3x the H100 the allocator would actually rent, and
646
+ # the submit-time affordability precheck refuses an affordable run on that inflated number.
647
+ names = tuple(
648
+ dict.fromkeys(
649
+ canonical_gpu(name) for name in (config.gpu_type, *config.gpu_type_fallbacks)
650
+ )
651
+ )
637
652
  elif provider == "auto":
638
653
  # `auto` ranks the RunPod pool: it is the default substrate, and the allocator only reaches a
639
654
  # lambda-only class after the cheaper runpod classes exhaust, so quoting one here would name
@@ -700,43 +715,79 @@ def _offline_gpu_shape(config: RunConfig) -> tuple[str, int, int, str, float]:
700
715
  )
701
716
  )
702
717
  if not ranked:
703
- # a pinned class is blocked by the class itself, so name it -- the pool-wide message would
704
- # report the widest validated shape, which is not hardware this quote was ever allowed to
705
- # use. `_wider_shape_remedy` searches only `names`, already narrowed to the pin, so the
706
- # `--gpus N` clause it appends can never name a shape the pin forbids. an unpinned run
707
- # falls through to the pool-wide message, which reports the count that would fit.
708
- remedy = _wider_shape_remedy(config, need, names)
709
- if config.gpu_type:
710
- info = GPU_INFO[canonical_gpu(config.gpu_type)]
711
- raise ValueError(
712
- f"exact GPU {info.name!r} cannot fit this run: it requires at least {need} GB"
713
- + (
714
- remedy
715
- or _catalog_check_remedy(config, need, names)
716
- or f". {vram_knob_advice(config.method).capitalize()}."
717
- )
718
- )
719
- raise ValueError(
720
- vram_fit_error_message(
721
- config.method,
722
- need,
723
- requested_gpu_count=ceiling,
724
- effective_gpu_count=safe_gpu_count,
725
- max_gpu_count=auto_cap,
726
- gpu_names=names,
727
- providers=None if provider == "auto" else (provider,),
728
- # same rule the ranking loop rejected shapes with, so the advice cannot name a
729
- # width the retry will not launch on.
730
- executed_width=lambda count: executed_gpu_count(config, count),
731
- # an offline quote does not know the configured fleet, so it cannot claim that
732
- # dropping a provider pin would make a wider shape purchasable.
733
- widenable_without_pin=None,
734
- )
718
+ _raise_no_fitting_shape(
719
+ config,
720
+ need,
721
+ names,
722
+ provider=provider,
723
+ ceiling=ceiling,
724
+ safe_gpu_count=safe_gpu_count,
725
+ auto_cap=auto_cap,
735
726
  )
736
727
  _cost, count, _combined, _per_card, gpu, hourly = min(ranked)
737
728
  return gpu, need, count, provider, hourly
738
729
 
739
730
 
731
+ def _raise_no_fitting_shape(
732
+ config: RunConfig,
733
+ need: float,
734
+ names: tuple[str, ...],
735
+ *,
736
+ provider: str,
737
+ ceiling: int | None,
738
+ safe_gpu_count: int,
739
+ auto_cap: int,
740
+ ) -> None:
741
+ """Reject a run no rentable shape fits, naming what the quote was allowed to rank."""
742
+ from flash.providers.base import GPU_INFO, canonical_gpu
743
+ from flash.providers.fit_errors import vram_fit_error_message, vram_knob_advice
744
+
745
+ # a pinned class is blocked by the class itself, so name it -- the pool-wide message would
746
+ # report the widest validated shape, which is not hardware this quote was ever allowed to
747
+ # use. `_wider_shape_remedy` searches only `names`, already narrowed to the pin, so the
748
+ # `--gpus N` clause it appends can never name a shape the pin forbids. an unpinned run
749
+ # falls through to the pool-wide message, which reports the count that would fit.
750
+ remedy = _wider_shape_remedy(config, need, names)
751
+ if config.gpu_type:
752
+ # name every acceptable class, not just the head: with fallbacks authored, reporting the
753
+ # head alone tells the user to fix a class that may not be the one that failed, and
754
+ # hides that the whole declared set was ranked and rejected.
755
+ declared = tuple(
756
+ GPU_INFO[canonical_gpu(name)].name
757
+ for name in (config.gpu_type, *config.gpu_type_fallbacks)
758
+ )
759
+ label = (
760
+ repr(declared[0])
761
+ if len(declared) == 1
762
+ else "none of " + ", ".join(repr(name) for name in declared)
763
+ )
764
+ raise ValueError(
765
+ f"exact GPU {label} cannot fit this run: it requires at least {need} GB"
766
+ + (
767
+ remedy
768
+ or _catalog_check_remedy(config, need, names)
769
+ or f". {vram_knob_advice(config.method).capitalize()}."
770
+ )
771
+ )
772
+ raise ValueError(
773
+ vram_fit_error_message(
774
+ config.method,
775
+ need,
776
+ requested_gpu_count=ceiling,
777
+ effective_gpu_count=safe_gpu_count,
778
+ max_gpu_count=auto_cap,
779
+ gpu_names=names,
780
+ providers=None if provider == "auto" else (provider,),
781
+ # same rule the ranking loop rejected shapes with, so the advice cannot name a
782
+ # width the retry will not launch on.
783
+ executed_width=lambda count: executed_gpu_count(config, count),
784
+ # an offline quote does not know the configured fleet, so it cannot claim that
785
+ # dropping a provider pin would make a wider shape purchasable.
786
+ widenable_without_pin=None,
787
+ )
788
+ )
789
+
790
+
740
791
  def _allocation_quote_shape(config: RunConfig, allocation) -> tuple[str, int, int, str, float]:
741
792
  """The (gpu, need, count, provider, per-card rate) billed against a SELECTED live candidate.
742
793
 
@@ -213,6 +213,11 @@ def runconfig_from_spec(spec) -> RunConfig:
213
213
  # and a caller that predates the preference has no such attribute to offer.
214
214
  providers=getattr(g, "providers", ()) or (),
215
215
  gpu_type=g.type,
216
+ # the rest of an ordered `[gpu] type` list. allocation cost-ranks every acceptable class, so
217
+ # dropping these here quotes the head alone and the affordability precheck can refuse a run
218
+ # whose cheaper authored fallback it would really have rented. read defensively for the same
219
+ # reason as `providers` above: this is not always a GpuSpec.
220
+ gpu_type_fallbacks=tuple(getattr(g, "type_fallbacks", ()) or ()),
216
221
  model_revision=spec.model_revision,
217
222
  disk_gb=float(getattr(g, "disk_gb", 0.0) or 0.0),
218
223
  # deliberately NOT spec.authored_gpu_count: this asks whether a shape has been RESOLVED
@@ -61,6 +61,12 @@ class RunConfig:
61
61
  sft_retained_examples: int | None = None
62
62
  # appended for the same positional-constructor reason as sft_retained_examples above.
63
63
  providers: tuple[str, ...] = ()
64
+ # the remaining classes an ordered `[gpu] type` list accepts, after gpu_type takes the head.
65
+ # allocation cost-ranks the whole acceptable set, so quoting the head alone prices a shape the
66
+ # run may never be given: an authored ["B200", "H100"] is quoted on B200 while allocate() would
67
+ # rent the cheaper H100, and the affordability precheck runs on that inflated estimate.
68
+ # appended for the same positional-constructor reason as the two fields above.
69
+ gpu_type_fallbacks: tuple[str, ...] = ()
64
70
 
65
71
  def __post_init__(self) -> None:
66
72
  object.__setattr__(self, "method", normalize_algorithm(self.method))
@@ -87,6 +93,24 @@ class RunConfig:
87
93
  if prov != "auto" and prov not in providers_for(exact):
88
94
  raise ValueError(f"provider {prov!r} cannot provision gpu_type {exact!r}")
89
95
  object.__setattr__(self, "gpu_type", exact)
96
+ # canonicalized and validated exactly like the head above, so a quote cannot rank a class the
97
+ # spec layer would have rejected. deduped against the head and each other because the
98
+ # ranking loop would otherwise price the same class twice.
99
+ fallbacks: list[str] = []
100
+ for entry in self.gpu_type_fallbacks or ():
101
+ if not isinstance(entry, str):
102
+ raise TypeError("gpu_type_fallbacks entries must be strings")
103
+ name = canonical_gpu(entry)
104
+ info = GPU_INFO.get(name)
105
+ if info is None or not info.validated:
106
+ raise ValueError(
107
+ f"gpu_type_fallbacks entry {name!r} must name an active validated GPU class"
108
+ )
109
+ if name != exact and name not in fallbacks:
110
+ fallbacks.append(name)
111
+ if fallbacks and not exact:
112
+ raise ValueError("gpu_type_fallbacks requires gpu_type")
113
+ object.__setattr__(self, "gpu_type_fallbacks", tuple(fallbacks))
90
114
  if not isinstance(self.model_revision, str):
91
115
  raise TypeError("model_revision must be a string")
92
116
  object.__setattr__(self, "model_revision", self.model_revision.strip())
@@ -97,6 +97,19 @@ _HB_UPLOAD_LOCK = threading.Lock()
97
97
  # Terminal/error commits wait longer — no later heartbeat can repair them.
98
98
  _HB_UPLOAD_LOCK_TIMEOUT_S = 30.0
99
99
  _HB_CRITICAL_UPLOAD_LOCK_TIMEOUT_S = 120.0
100
+ # True while a thread holds _HB_UPLOAD_LOCK and is inside the HF commit. Read under _HB_LOCK.
101
+ #
102
+ # The throttle clock (_HB_LAST_UPLOAD) only advances AFTER a commit lands, so during a slow HF
103
+ # commit every other throttled caller still computes upload_due=True, walks into
104
+ # _HB_UPLOAD_LOCK.acquire() and blocks there for up to the acquire timeout -- 30s, or 120s on a
105
+ # critical stage. That stalls the liveness daemon, and `liveness_heartbeat`'s join delays leaving
106
+ # the wrapped stage by the same window.
107
+ #
108
+ # A marker rather than claiming the clock before the upload: an optimistic claim has to be rolled
109
+ # back when the commit fails, and the rollback has to decide whether a NEWER heartbeat already
110
+ # moved the clock (the reason the old code carried a claim sequence). This says only "a commit is
111
+ # in flight right now", is cleared in a finally, and so cannot strand the throttle on a failure.
112
+ _HB_UPLOAD_IN_FLIGHT = False
100
113
  # retain at least one metric row per second across the 900s training heartbeat throttle window.
101
114
  GRPO_METRIC_HISTORY_LIMIT = 1024
102
115
 
@@ -127,6 +140,12 @@ def _console_heartbeat_snapshot(
127
140
  return json.dumps(console_payload)
128
141
 
129
142
 
143
+ def _set_upload_in_flight(value: bool) -> None:
144
+ """Mark whether an HF heartbeat commit is running. Call with _HB_LOCK held."""
145
+ global _HB_UPLOAD_IN_FLIGHT
146
+ _HB_UPLOAD_IN_FLIGHT = value
147
+
148
+
130
149
  def _heartbeat_upload_due(
131
150
  stage: str,
132
151
  *,
@@ -140,6 +159,22 @@ def _heartbeat_upload_due(
140
159
  """return eligibility from committed throttle state while _HB_LOCK is held."""
141
160
  if initial or _is_critical_stage(stage):
142
161
  return True
162
+ # a commit is already in flight and will advance the throttle clock when it lands. an unforced
163
+ # ping would only queue behind it on _HB_UPLOAD_LOCK, publish a snapshot older than the one
164
+ # being written, and block its caller for the acquire timeout -- 30s, or 120s on a critical
165
+ # stage. that is what stalls the liveness daemon, whose `join` then delays leaving the wrapped
166
+ # stage by the same window. skipping loses nothing: the in-flight commit carries this stage.
167
+ #
168
+ # three exemptions, all above or inside this check:
169
+ # - initial and critical stages return True earlier: a terminal or error snapshot has no later
170
+ # heartbeat to repair it, so it must queue and land.
171
+ # - `force` is excluded here because it carries billing state. a forced commit marks a
172
+ # DISTINCT completed step, and a cancel bills the last step a heartbeat recorded, so
173
+ # dropping one to avoid a wait could under-report a step the run really finished.
174
+ # the daemon's own pings are never forced (liveness and keepalive both leave it False), so this
175
+ # exemption does not reopen the stall it fixes.
176
+ if _HB_UPLOAD_IN_FLIGHT and not force:
177
+ return False
143
178
  if _w._HB_TERMINAL_ONLY:
144
179
  return (
145
180
  _w._HB_LAST_UPLOAD == 0.0 or (now - _w._HB_LAST_UPLOAD) >= _HB_TERMINAL_ONLY_INTERVAL_S
@@ -234,12 +269,18 @@ def heartbeat(
234
269
  up = f"/tmp/.hb-upload-{os.getpid()}-{threading.get_ident()}.json"
235
270
  with open(up, "w") as f:
236
271
  f.write(snapshot)
272
+ with _HB_LOCK:
273
+ _set_upload_in_flight(True)
237
274
  try:
238
275
  if initial:
239
276
  committed = _w.hf_upload_file(up, "heartbeat.json", required=True)
240
277
  else:
241
278
  committed = _w.hf_upload_file(up, "heartbeat.json")
242
279
  finally:
280
+ # cleared before the throttle clock is advanced below, and in a finally so a
281
+ # raising upload cannot leave every later heartbeat permanently skipped.
282
+ with _HB_LOCK:
283
+ _set_upload_in_flight(False)
243
284
  with contextlib.suppress(OSError):
244
285
  os.remove(up)
245
286
  if committed is False:
@@ -5,7 +5,7 @@ The fla/tilelang/cudart fixup group stays IN THIS MODULE on purpose: tests monke
5
5
  through the patched module globals. Do NOT move this group into a submodule.
6
6
 
7
7
  NOTE: ``tests/test_worker_stack.py`` reads THIS file as TEXT to assert the fla SHA /
8
- TILELANG_PIN stay in lockstep with WORKER_DEPS / Dockerfile.worker.
8
+ TILELANG_PIN stay in lockstep with Dockerfile.worker.
9
9
  """
10
10
 
11
11
  from __future__ import annotations
@@ -315,7 +315,7 @@ def _ensure_fla_fastpath_on_hopper() -> None:
315
315
  return False
316
316
  return rc == 0
317
317
 
318
- # 0.1.12 double-registers the TVM-FFI runtime -> `import tilelang` aborts; keep in lockstep with WORKER_DEPS / Dockerfile.
318
+ # 0.1.12 double-registers the TVM-FFI runtime -> `import tilelang` aborts; keep in lockstep with Dockerfile.worker.
319
319
  TVM_FFI_PIN = "0.1.11"
320
320
  TILELANG_PIN = "0.1.11"
321
321
 
@@ -334,7 +334,7 @@ def _ensure_fla_fastpath_on_hopper() -> None:
334
334
  fla_ok = True
335
335
  if not (_have("fla") and _have("fla.modules")):
336
336
  _remove_fla_from_disk()
337
- # Pinned commit — keep in lockstep with WORKER_DEPS / Dockerfile.worker.
337
+ # Pinned commit — keep in lockstep with Dockerfile.worker.
338
338
  fla_ok = _pip(
339
339
  "--no-deps",
340
340
  "git+https://github.com/fla-org/flash-linear-attention.git"
@@ -46,7 +46,7 @@ class GitHubUnavailableError(GitHubTransientError):
46
46
 
47
47
 
48
48
  class GitHubPermanentError(RuntimeError):
49
- """GitHub answered, and the answer will not change on a retry: a 404 or a 422.
49
+ """GitHub answered, and the answer will not change on a retry: 401, 403, 404, or 422.
50
50
 
51
51
  Deliberately NOT a GitHubTransientError. Waiting is the right response to a blip and the wrong
52
52
  response to a typo, and the two are indistinguishable once both are a bare RuntimeError -- which
@@ -57,6 +57,10 @@ class GitHubPermanentError(RuntimeError):
57
57
  read, rather than leaking its existence with a 403. Both are permanent for this caller: no
58
58
  amount of retrying makes an unreadable ref resolvable, and the fix (check the name, or grant the
59
59
  token access) is the user's either way. The message carries GitHub's own text so it names which.
60
+
61
+ The credential codes reach here only after the rate-limit shapes (429, and the 403 that says
62
+ rate limit) have been claimed as transient, so a 401 or a surviving 403 is a token this plane
63
+ cannot fix by waiting: invalid, expired, or missing the scope. Same user-side fix as a typo.
60
64
  """
61
65
 
62
66
 
@@ -285,9 +285,13 @@ def _urlopen(
285
285
  ) from exc
286
286
  # 404 (no such repo, or one the token cannot read) and 422 (a ref that does not exist,
287
287
  # e.g. "No commit found for SHA: main" on a master-default repo) are settled answers.
288
+ # 401 and a non-rate-limit 403 join them: the rate-limit shapes are already claimed
289
+ # above, so what is left is a token this plane cannot fix by waiting -- invalid,
290
+ # expired, or lacking the scope. deferring those rents a GPU to rediscover the same
291
+ # credential error on the worker.
288
292
  # Typed so the submit-time pin can fail closed on them while still deferring a blip;
289
293
  # every other code keeps the untyped RuntimeError it has always raised.
290
- if exc.code in (404, 422):
294
+ if exc.code in (401, 403, 404, 422):
291
295
  raise GitHubPermanentError(
292
296
  f"GitHub environment request failed ({exc.code}): {body[:500]}"
293
297
  ) from exc
@@ -257,15 +257,31 @@ def hf_upload(
257
257
  return False
258
258
 
259
259
 
260
- def _upload_console_snapshot(payload: dict, console: str, mode: str, extra: str = "") -> bool:
261
- """Upload one console snapshot from an isolated process."""
262
- tail_path = console + ".tail"
260
+ def _upload_console_snapshot(
261
+ payload: dict, console: str, mode: str, extra: str = "", final: bool = False
262
+ ) -> bool:
263
+ """Upload one console snapshot from an isolated process.
264
+
265
+ The periodic snapshot and the terminal one never share a scratch file or a repo destination.
266
+ Reaping the periodic child at teardown is best-effort, so one killed mid-write would otherwise
267
+ truncate the scratch file the terminal snapshot is uploading, or overwrite the terminal artifact
268
+ itself -- losing the failure detail the control plane reads, including the wall-clock-cap marker.
269
+
270
+ The terminal snapshot keeps the canonical ``console_<mode>.txt`` the control plane reads; the
271
+ periodic one takes the attempt-scoped name it reads separately, matching the serverless handler,
272
+ so a retry cannot overwrite the attempt that reproduced the failure. This module can never
273
+ import flash, so the format is spelled out here and pinned against
274
+ ``flash.adapters.artifacts.attempt_scoped_artifact_name`` by test rather than by coincidence --
275
+ a name the reader does not expect looks exactly like a worker that uploaded nothing.
276
+ """
277
+ kind = "" if final else f"_attempt{payload.get('attempt', 0)}"
278
+ tail_path = f"{console}{kind}.tail"
263
279
  tail = _read_console_tail(console, 64_000, secrets=_payload_secrets(payload))
264
280
  if extra:
265
281
  tail += extra
266
282
  with open(tail_path, "w", encoding="utf-8", errors="replace") as f:
267
283
  f.write(_safe_detail(tail, 64_000, secrets=_payload_secrets(payload)))
268
- return hf_upload(payload, tail_path, f"console_{mode}.txt")
284
+ return hf_upload(payload, tail_path, f"console_{mode}{kind}.txt")
269
285
 
270
286
 
271
287
  def _console_upload_loop(
@@ -453,7 +469,7 @@ def _upload_console_tail_bounded(
453
469
  context = multiprocessing.get_context("spawn")
454
470
  process = context.Process(
455
471
  target=_upload_console_snapshot,
456
- args=(payload, console, mode, extra),
472
+ args=(payload, console, mode, extra, True),
457
473
  daemon=True,
458
474
  )
459
475
  process.start()
@@ -77,8 +77,13 @@ def _run_console_upload_loop(console: str, interval_s: float, stop_upload, *, up
77
77
  prevents a flapping run from turning the poll cadence into the commit cadence.
78
78
 
79
79
  Before any heartbeat commits, one additional setup snapshot lands before the fixed 3000-second
80
- teardown. It does not enter the steady rate: the first committed heartbeat moves the deadline to
81
- the normal interval. failed uploads change no upload state, so the next poll retries.
80
+ teardown. It does not enter the steady rate: the first committed heartbeat promotes the deadline
81
+ to the normal interval, so a run that commits before 600 seconds never spends that write. the
82
+ promotion is skipped while ``due`` holds, so it only ever moves a deadline that has not arrived.
83
+ A 600-second deadline that already expired with nothing committed still spends its snapshot --
84
+ the startup evidence it exists for -- and a failed upload on that same poll leaves the deadline
85
+ due, so the next poll retries rather than waiting out the hour. Once promoted the deadline is the
86
+ hourly interval, so the guard cannot re-fire early and needs no separate first-commit flag.
82
87
  """
83
88
  poll_s = min(_CONSOLE_UPLOAD_POLL_S, interval_s)
84
89
  due_s = min(_CONSOLE_UPLOAD_FIRST_SNAPSHOT_S, interval_s)
@@ -87,14 +92,13 @@ def _run_console_upload_loop(console: str, interval_s: float, stop_upload, *, up
87
92
  while not stop_upload.wait(poll_s):
88
93
  since += poll_s
89
94
  cursor, eof, staged, beats = _console_progress(console, max(cursor, 0))
90
- had_committed = ever
91
95
  ever = ever or bool(staged)
92
- if ever and not had_committed and sent >= 0:
96
+ due = since >= due_s
97
+ if ever and not due:
93
98
  due_s = interval_s
94
99
  made_progress = staged if ever else beats
95
100
  armed = armed or bool(made_progress)
96
101
  quiet = 0.0 if made_progress else quiet + 1
97
- due = since >= due_s
98
102
  cap = armed and quiet >= _CONSOLE_UPLOAD_QUIET_POLLS
99
103
  wedged = cap and spent < _CONSOLE_UPLOAD_CREDITS and not due
100
104
  if eof == sent or not (due or wedged):
@@ -0,0 +1,5 @@
1
+ """Standalone host-side helper programs shipped in the instance-bootstrap capsule.
2
+
3
+ Each module here runs as its own `python3 <file>` process on the rented box, NOT as an import of
4
+ the flash package. They must stay stdlib-only and self-contained.
5
+ """