freesolo-flash-dev 1.2.53__tar.gz → 1.2.59__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 (576) hide show
  1. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/CHANGELOG.md +11 -0
  2. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/PKG-INFO +1 -1
  3. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/core/spec.py +4 -23
  4. freesolo_flash_dev-1.2.59/flash/core/spec_persistence.py +123 -0
  5. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/runpod/job_execution.py +42 -4
  6. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/runner/__init__.py +2 -13
  7. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/runner/costs.py +2 -44
  8. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/runner/preparation.py +8 -153
  9. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/runner/status.py +4 -35
  10. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/runner/submit.py +1 -19
  11. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/schema/__init__.py +2 -6
  12. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/serve/urls.py +1 -2
  13. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/server/platform/runtime.py +3 -34
  14. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/pyproject.toml +2 -2
  15. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_jobs.py +207 -13
  16. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_runmgmt.py +0 -65
  17. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_server_api.py +1 -7
  18. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_server_envs_coverage.py +0 -1
  19. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_spec_and_validation.py +1 -465
  20. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_spec_contract_bytes.py +0 -64
  21. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_warmstart_cross_repo.py +3 -6
  22. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/uv.lock +1 -1
  23. freesolo_flash_dev-1.2.53/flash/core/spec_persistence.py +0 -227
  24. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/.dockerignore +0 -0
  25. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/.env.example +0 -0
  26. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/.github/CODEOWNERS +0 -0
  27. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  28. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  29. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  30. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  31. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/.github/dependabot.yml +0 -0
  32. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/.github/workflows/auto-rebake.yml +0 -0
  33. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/.github/workflows/bake-kernel-cache.yml +0 -0
  34. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/.github/workflows/ci.yml +0 -0
  35. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/.github/workflows/main-source-guard.yml +0 -0
  36. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/.github/workflows/notify-tests-repo.yml +0 -0
  37. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/.github/workflows/publish-dev.yml +0 -0
  38. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/.github/workflows/publish-image.yml +0 -0
  39. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/.github/workflows/publish.yml +0 -0
  40. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/.github/workflows/version-parity.yml +0 -0
  41. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/.github/workflows/worker-image.yml +0 -0
  42. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/.gitignore +0 -0
  43. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/CODE_OF_CONDUCT.md +0 -0
  44. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/CONTRIBUTING.md +0 -0
  45. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/Dockerfile +0 -0
  46. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/Dockerfile.worker +0 -0
  47. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/LICENSE +0 -0
  48. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/NOTICE +0 -0
  49. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/README.md +0 -0
  50. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/SECURITY.md +0 -0
  51. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/SELF_HOSTING.md +0 -0
  52. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/build/kernel_cache/.gitignore +0 -0
  53. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/build/kernel_cache/.keep +0 -0
  54. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/deploy/infisical/README.md +0 -0
  55. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/deploy/infisical/entrypoint.sh +0 -0
  56. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/docker/Dockerfile.kernelcache +0 -0
  57. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/docker/Dockerfile.kernelcache.relayer +0 -0
  58. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/docker/bake_kernel_cache.py +0 -0
  59. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/docker/bake_pod_entry.py +0 -0
  60. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/docker/extract_cudart_fix.py +0 -0
  61. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/docker/kernel_fingerprint.py +0 -0
  62. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/docker/make_rp_handler.py +0 -0
  63. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/__init__.py +0 -0
  64. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/_internal/__init__.py +0 -0
  65. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/_internal/channel.py +0 -0
  66. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/_internal/diagnostics.py +0 -0
  67. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/_internal/fileio.py +0 -0
  68. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/_internal/logging.py +0 -0
  69. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/_internal/paths.py +0 -0
  70. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/adapters/__init__.py +0 -0
  71. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/adapters/artifacts.py +0 -0
  72. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/adapters/fused_experts.py +0 -0
  73. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/adapters/lora_rank.py +0 -0
  74. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/cli/__init__.py +0 -0
  75. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/cli/__main__.py +0 -0
  76. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/cli/commands/__init__.py +0 -0
  77. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/cli/commands/deploy.py +0 -0
  78. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/cli/commands/env/__init__.py +0 -0
  79. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/cli/commands/env/episode.py +0 -0
  80. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/cli/commands/env/eval.py +0 -0
  81. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/cli/commands/env/eval_args.py +0 -0
  82. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/cli/commands/env/imports.py +0 -0
  83. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/cli/commands/env/list.py +0 -0
  84. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/cli/commands/env/push.py +0 -0
  85. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/cli/commands/env/retained.py +0 -0
  86. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/cli/commands/env/setup.py +0 -0
  87. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/cli/commands/env/test.py +0 -0
  88. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/cli/commands/env/test_evaluations.py +0 -0
  89. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/cli/commands/env/test_params.py +0 -0
  90. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/cli/commands/env/test_warnings.py +0 -0
  91. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/cli/commands/prompt_budget.py +0 -0
  92. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/cli/commands/traces.py +0 -0
  93. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/cli/commands/train_cost.py +0 -0
  94. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/cli/scaffold/TRAINING.md +0 -0
  95. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/cli/scaffold/__init__.py +0 -0
  96. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/cli/ui/__init__.py +0 -0
  97. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/cli/ui/cost.py +0 -0
  98. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/cli/ui/env_panels.py +0 -0
  99. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/cli/ui/heartbeat.py +0 -0
  100. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/cli/ui/render.py +0 -0
  101. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/cli/ui/tables.py +0 -0
  102. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/cli/ui/tty.py +0 -0
  103. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/client/__init__.py +0 -0
  104. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/client/config.py +0 -0
  105. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/client/freesolo_api.py +0 -0
  106. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/client/http.py +0 -0
  107. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/client/runtime_secrets.py +0 -0
  108. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/client/shapes.py +0 -0
  109. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/client/specs.py +0 -0
  110. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/client/streaming.py +0 -0
  111. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/content/__init__.py +0 -0
  112. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/content/multimodal.py +0 -0
  113. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/content/structured_outputs.py +0 -0
  114. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/content/thinking.py +0 -0
  115. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/core/__init__.py +0 -0
  116. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/core/catalog.py +0 -0
  117. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/cost/__init__.py +0 -0
  118. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/cost/analytical.py +0 -0
  119. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/cost/facts.py +0 -0
  120. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/cost/spec.py +0 -0
  121. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/cost/types.py +0 -0
  122. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/__init__.py +0 -0
  123. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/plan/__init__.py +0 -0
  124. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/plan/kv_sizing.py +0 -0
  125. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/plan/model_config_probe.py +0 -0
  126. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/plan/prompt_budget.py +0 -0
  127. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/plan/recipe.py +0 -0
  128. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/plan/steps.py +0 -0
  129. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/plan/vram.py +0 -0
  130. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/profiling/__init__.py +0 -0
  131. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/profiling/dataset_profile.py +0 -0
  132. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/profiling/reasoning_render.py +0 -0
  133. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/profiling/sft_workload.py +0 -0
  134. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/profiling/tokenizer.py +0 -0
  135. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/profiling/workload_profile.py +0 -0
  136. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/result/__init__.py +0 -0
  137. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/result/accounting.py +0 -0
  138. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/result/rollout_samples.py +0 -0
  139. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/__init__.py +0 -0
  140. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/__main__.py +0 -0
  141. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/backend_common.py +0 -0
  142. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/entry/__init__.py +0 -0
  143. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/entry/opd.py +0 -0
  144. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/entry/rl.py +0 -0
  145. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/entry/sft.py +0 -0
  146. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/io/__init__.py +0 -0
  147. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/io/heartbeat.py +0 -0
  148. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/io/hf.py +0 -0
  149. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/io/prefetch.py +0 -0
  150. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/io/wandb_log.py +0 -0
  151. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/model/__init__.py +0 -0
  152. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/model/adapter.py +0 -0
  153. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/model/chatml_mask.py +0 -0
  154. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/model/decoding.py +0 -0
  155. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/model/lora.py +0 -0
  156. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/model/packing.py +0 -0
  157. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/opd_train.py +0 -0
  158. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/opd_train_runner.py +0 -0
  159. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/perf/__init__.py +0 -0
  160. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/perf/diagnostics.py +0 -0
  161. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/perf/lifecycle.py +0 -0
  162. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/perf/liger.py +0 -0
  163. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/perf/memory.py +0 -0
  164. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/rl_train.py +0 -0
  165. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/rl_train_runner.py +0 -0
  166. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/runtime/__init__.py +0 -0
  167. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/runtime/kernel_warmup.py +0 -0
  168. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/runtime/pkg_proxy.py +0 -0
  169. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/runtime/rng.py +0 -0
  170. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/score_batcher.py +0 -0
  171. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/sft_train.py +0 -0
  172. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/sft_train_runner.py +0 -0
  173. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/teacher/__init__.py +0 -0
  174. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/teacher/client.py +0 -0
  175. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/teacher/encoding.py +0 -0
  176. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/teacher/tokenizer_align.py +0 -0
  177. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/__init__.py +0 -0
  178. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/core/__init__.py +0 -0
  179. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/core/checkpoint_lifecycle.py +0 -0
  180. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/core/child/__init__.py +0 -0
  181. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/core/child/glue.py +0 -0
  182. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/core/child/runtime.py +0 -0
  183. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/core/step_timing.py +0 -0
  184. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/finalize.py +0 -0
  185. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/opd/__init__.py +0 -0
  186. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/opd/batching.py +0 -0
  187. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/opd/bridge.py +0 -0
  188. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/opd/child/__init__.py +0 -0
  189. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/opd/child/bridge.py +0 -0
  190. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/opd/child/entry.py +0 -0
  191. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/opd/child/multiturn.py +0 -0
  192. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/opd/child/plugin.py +0 -0
  193. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/opd/child/replay_guard.py +0 -0
  194. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/opd/child/runtime.py +0 -0
  195. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/opd/child/structured.py +0 -0
  196. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/opd/failures.py +0 -0
  197. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/opd/gkd.py +0 -0
  198. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/opd/multiturn_validation.py +0 -0
  199. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/opd/overrides.py +0 -0
  200. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/opd/prompts.py +0 -0
  201. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/opd/reporting.py +0 -0
  202. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/opd/scoring.py +0 -0
  203. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/opd/state.py +0 -0
  204. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/opd/validation.py +0 -0
  205. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/rl/__init__.py +0 -0
  206. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/rl/checkpoints.py +0 -0
  207. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/rl/child/__init__.py +0 -0
  208. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/rl/child/entry.py +0 -0
  209. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/rl/child/multiturn.py +0 -0
  210. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/rl/child/patches.py +0 -0
  211. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/rl/child/plugin.py +0 -0
  212. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/rl/config.py +0 -0
  213. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/rl/inputs.py +0 -0
  214. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/rl/multi_turn.py +0 -0
  215. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/rl/reward_module.py +0 -0
  216. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/rl/scoring.py +0 -0
  217. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/rl/single_turn.py +0 -0
  218. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/rl/verl_config.py +0 -0
  219. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/sft/__init__.py +0 -0
  220. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/sft/checkpoints.py +0 -0
  221. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/sft/child/entry.py +0 -0
  222. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/sft/child/plugin.py +0 -0
  223. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/sft/config.py +0 -0
  224. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/verl/__init__.py +0 -0
  225. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/verl/capabilities.py +0 -0
  226. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/verl/checkpoints.py +0 -0
  227. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/verl/child_io.py +0 -0
  228. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/verl/diagnostics.py +0 -0
  229. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/verl/parallelism.py +0 -0
  230. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker/verl/parent_work.py +0 -0
  231. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/engine/worker_entrypoint.py +0 -0
  232. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/envs/__init__.py +0 -0
  233. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/envs/adapter.py +0 -0
  234. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/envs/base.py +0 -0
  235. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/envs/cache_security.py +0 -0
  236. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/envs/dataset_selection.py +0 -0
  237. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/envs/evaluations.py +0 -0
  238. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/envs/identity.py +0 -0
  239. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/envs/loader.py +0 -0
  240. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/envs/namespace_listing.py +0 -0
  241. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/envs/package/__init__.py +0 -0
  242. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/envs/package/limits.py +0 -0
  243. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/envs/package/unpack.py +0 -0
  244. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/envs/pull.py +0 -0
  245. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/__init__.py +0 -0
  246. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/_lifecycle/__init__.py +0 -0
  247. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/_lifecycle/auth.py +0 -0
  248. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/_lifecycle/bootstrap.py +0 -0
  249. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/_lifecycle/bootstrap_console.py +0 -0
  250. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/_lifecycle/bootstrap_pip.py +0 -0
  251. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/_lifecycle/bootstrap_secrets.py +0 -0
  252. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/_lifecycle/deadline.py +0 -0
  253. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/_lifecycle/host/__init__.py +0 -0
  254. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/_lifecycle/host/deadline_sleep.py +0 -0
  255. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/_lifecycle/host/failmark.py +0 -0
  256. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/_lifecycle/host/hostlog.py +0 -0
  257. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/_lifecycle/http.py +0 -0
  258. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/_lifecycle/instance.py +0 -0
  259. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/_lifecycle/poll.py +0 -0
  260. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/_lifecycle/poll_instance.py +0 -0
  261. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/_lifecycle/provider.py +0 -0
  262. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/_lifecycle/terminal_artifacts.py +0 -0
  263. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/_lifecycle/worker.py +0 -0
  264. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/allocator.py +0 -0
  265. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/artifacts/__init__.py +0 -0
  266. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/artifacts/hf.py +0 -0
  267. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/artifacts/preload_runpod.py +0 -0
  268. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/artifacts/weight_cache.py +0 -0
  269. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/base.py +0 -0
  270. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/fit_errors.py +0 -0
  271. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/lambda_/__init__.py +0 -0
  272. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/lambda_/api.py +0 -0
  273. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/lambda_/auth.py +0 -0
  274. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/lambda_/gpus.py +0 -0
  275. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/lambda_/jobs/__init__.py +0 -0
  276. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/lambda_/jobs/builders.py +0 -0
  277. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/lambda_/jobs/reap.py +0 -0
  278. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/lambda_/preflight.py +0 -0
  279. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/lambda_/pricing.py +0 -0
  280. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/preflight.py +0 -0
  281. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/realized.py +0 -0
  282. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/runpod/__init__.py +0 -0
  283. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/runpod/api.py +0 -0
  284. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/runpod/auth.py +0 -0
  285. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/runpod/cost.py +0 -0
  286. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/runpod/gpus.py +0 -0
  287. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/runpod/jobs.py +0 -0
  288. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/runpod/preflight.py +0 -0
  289. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/runpod/pricing.py +0 -0
  290. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/runpod/resources.py +0 -0
  291. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/runpod/serverless/__init__.py +0 -0
  292. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/runpod/serverless/endpoints.py +0 -0
  293. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/sharding.py +0 -0
  294. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/vast/__init__.py +0 -0
  295. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/vast/api.py +0 -0
  296. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/vast/auth.py +0 -0
  297. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/vast/jobs/__init__.py +0 -0
  298. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/vast/jobs/builders.py +0 -0
  299. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/vast/preflight.py +0 -0
  300. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/providers/vast/pricing.py +0 -0
  301. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/py.typed +0 -0
  302. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/runner/artifacts.py +0 -0
  303. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/runner/attempts.py +0 -0
  304. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/runner/deadlines.py +0 -0
  305. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/runner/reconciliation.py +0 -0
  306. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/runner/results/__init__.py +0 -0
  307. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/runner/results/checkpoints.py +0 -0
  308. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/runner/results/verified_revisions.py +0 -0
  309. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/runner/supervise/__init__.py +0 -0
  310. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/runner/supervise/attach.py +0 -0
  311. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/runner/supervise/deploy.py +0 -0
  312. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/runner/supervise/lifecycle.py +0 -0
  313. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/runner/supervise/recovery.py +0 -0
  314. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/runner/supervise/retry_decision.py +0 -0
  315. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/runner/supervise/seed_submission.py +0 -0
  316. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/runner/supervise/transitions.py +0 -0
  317. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/runner/weight_cache.py +0 -0
  318. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/runtime_capsule/__init__.py +0 -0
  319. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/runtime_capsule/build.py +0 -0
  320. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/runtime_capsule/manifest.py +0 -0
  321. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/runtime_capsule/profiles.py +0 -0
  322. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/schema/fields.py +0 -0
  323. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/serve/__init__.py +0 -0
  324. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/serve/adapter_check.py +0 -0
  325. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/serve/deploy.py +0 -0
  326. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/serve/errors.py +0 -0
  327. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/serve/export.py +0 -0
  328. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/serve/preflight.py +0 -0
  329. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/serve/responses.py +0 -0
  330. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/serve/streaming.py +0 -0
  331. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/serve/thinking.py +0 -0
  332. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/server/__init__.py +0 -0
  333. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/server/__main__.py +0 -0
  334. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/server/app.py +0 -0
  335. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/server/billing/__init__.py +0 -0
  336. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/server/billing/charges.py +0 -0
  337. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/server/billing/retry.py +0 -0
  338. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/server/domain/__init__.py +0 -0
  339. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/server/domain/checkpoints.py +0 -0
  340. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/server/domain/environment_registry.py +0 -0
  341. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/server/domain/envs.py +0 -0
  342. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/server/domain/projects.py +0 -0
  343. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/server/domain/reconcile.py +0 -0
  344. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/server/domain/repo_cleanup.py +0 -0
  345. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/server/domain/run_registry.py +0 -0
  346. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/server/domain/teacher_broker.py +0 -0
  347. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/server/domain/teacher_errors.py +0 -0
  348. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/server/domain/teacher_requests.py +0 -0
  349. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/server/platform/__init__.py +0 -0
  350. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/server/platform/auth.py +0 -0
  351. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/server/platform/db.py +0 -0
  352. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/server/platform/deps.py +0 -0
  353. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/server/platform/internal_client.py +0 -0
  354. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/server/platform/locks.py +0 -0
  355. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/server/routes/__init__.py +0 -0
  356. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/server/routes/envs.py +0 -0
  357. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/server/routes/meta.py +0 -0
  358. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/server/routes/runs.py +0 -0
  359. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/server/routes/serving.py +0 -0
  360. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/server/routes/serving_completion.py +0 -0
  361. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/server/routes/serving_revisions.py +0 -0
  362. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/server/routes/serving_smoke.py +0 -0
  363. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/server/routes/teacher.py +0 -0
  364. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/teacher/__init__.py +0 -0
  365. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/teacher/limits.py +0 -0
  366. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/flash/teacher/retry_contract.py +0 -0
  367. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/scripts/build_dev_dist.py +0 -0
  368. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/scripts/check_file_size.py +0 -0
  369. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/scripts/check_function_size.py +0 -0
  370. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/scripts/check_verl_pin_exists.py +0 -0
  371. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/scripts/scrub_history.sh +0 -0
  372. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/__init__.py +0 -0
  373. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/_helpers/__init__.py +0 -0
  374. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/_helpers/profile.py +0 -0
  375. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/_helpers/runner.py +0 -0
  376. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/_helpers/specs.py +0 -0
  377. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/_helpers/teacher.py +0 -0
  378. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/_helpers/vast.py +0 -0
  379. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/conftest.py +0 -0
  380. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/fixtures/math_eval.jsonl +0 -0
  381. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/fixtures/math_train.jsonl +0 -0
  382. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/live/__init__.py +0 -0
  383. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/live/conftest.py +0 -0
  384. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/live/test_lambda_live.py +0 -0
  385. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/live/test_runpod_live.py +0 -0
  386. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/live/test_sft_thinking_render_live.py +0 -0
  387. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/live/test_vast_live.py +0 -0
  388. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_accounting_coverage.py +0 -0
  389. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_adapter_shard_completeness.py +0 -0
  390. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_agent_flash_cli_contract.py +0 -0
  391. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_algorithms.py +0 -0
  392. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_allocator.py +0 -0
  393. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_backend_common.py +0 -0
  394. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_backend_jobspec_contract.py +0 -0
  395. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_bake_kernel_cache.py +0 -0
  396. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_base_model_provenance.py +0 -0
  397. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_billing_retry.py +0 -0
  398. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_build_context_contract.py +0 -0
  399. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_cancel_remote.py +0 -0
  400. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_catalog_consistency.py +0 -0
  401. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_catalog_only_models.py +0 -0
  402. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_charge_pricing.py +0 -0
  403. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_checkpoint_lifecycle.py +0 -0
  404. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_checkpoints.py +0 -0
  405. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_cli_commands.py +0 -0
  406. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_cli_commands_coverage.py +0 -0
  407. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_cli_credential_shadowing.py +0 -0
  408. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_cli_errors.py +0 -0
  409. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_cli_estimate.py +0 -0
  410. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_cli_gpus_flag.py +0 -0
  411. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_cli_help.py +0 -0
  412. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_cli_main_coverage.py +0 -0
  413. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_cli_managed.py +0 -0
  414. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_cli_render_coverage.py +0 -0
  415. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_cli_render_theme.py +0 -0
  416. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_cli_traces.py +0 -0
  417. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_cli_wandb_warning.py +0 -0
  418. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_client.py +0 -0
  419. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_client_import_purity.py +0 -0
  420. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_client_server_integration.py +0 -0
  421. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_client_stream_reads.py +0 -0
  422. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_config_env_vars.py +0 -0
  423. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_config_overrides.py +0 -0
  424. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_console_upload.py +0 -0
  425. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_controlled_experiment_repairs.py +0 -0
  426. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_cost_analytical.py +0 -0
  427. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_cost_equation.py +0 -0
  428. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_cost_estimate.py +0 -0
  429. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_cost_hardware.py +0 -0
  430. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_cost_models.py +0 -0
  431. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_dataset_profile.py +0 -0
  432. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_deploy_alias_move_warning.py +0 -0
  433. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_deploy_latency.py +0 -0
  434. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_dev_channel.py +0 -0
  435. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_disk_gb.py +0 -0
  436. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_endpoint_name.py +0 -0
  437. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_env_cache_evict.py +0 -0
  438. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_env_delete.py +0 -0
  439. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_env_download.py +0 -0
  440. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_env_download_api.py +0 -0
  441. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_env_evaluations.py +0 -0
  442. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_env_list_api.py +0 -0
  443. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_env_list_cli.py +0 -0
  444. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_env_list_hub.py +0 -0
  445. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_env_no_install.py +0 -0
  446. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_env_publish.py +0 -0
  447. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_env_pull.py +0 -0
  448. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_env_pull_coverage.py +0 -0
  449. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_env_pull_loader_coverage.py +0 -0
  450. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_env_pull_managed_control_plane.py +0 -0
  451. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_env_push.py +0 -0
  452. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_env_rate_limit_resolve.py +0 -0
  453. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_env_ref_pinning.py +0 -0
  454. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_env_test.py +0 -0
  455. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_envs_coverage.py +0 -0
  456. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_export.py +0 -0
  457. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_flash_mvp.py +0 -0
  458. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_flash_worker.py +0 -0
  459. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_flashinfer_cache_dirs.py +0 -0
  460. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_freesolo_api_transport.py +0 -0
  461. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_fused_expert_warmstart.py +0 -0
  462. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_github_urlopen_retry.py +0 -0
  463. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_gpu_type_single_field.py +0 -0
  464. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_gpus.py +0 -0
  465. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_grpo_params.py +0 -0
  466. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_grpo_resident_sizing.py +0 -0
  467. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_grpo_reward_batching.py +0 -0
  468. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_health_liveness.py +0 -0
  469. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_hf_retry.py +0 -0
  470. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_idle_endpoint_reaper.py +0 -0
  471. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_infisical_secrets.py +0 -0
  472. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_instance_bootstrap_coverage.py +0 -0
  473. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_internal_client.py +0 -0
  474. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_kernel_cache.py +0 -0
  475. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_kernel_fingerprint.py +0 -0
  476. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_kv_util.py +0 -0
  477. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_lambda_api_coverage.py +0 -0
  478. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_lambda_runner.py +0 -0
  479. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_logging.py +0 -0
  480. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_login_perms.py +0 -0
  481. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_lora_rank_coverage.py +0 -0
  482. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_lora_rank_preflight.py +0 -0
  483. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_managed_config_fields.py +0 -0
  484. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_managed_hf_repo.py +0 -0
  485. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_metrics_schema_agent_contract.py +0 -0
  486. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_mig_guard.py +0 -0
  487. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_multi_gpu_gate.py +0 -0
  488. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_multimodal_training.py +0 -0
  489. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_named_reward_metrics.py +0 -0
  490. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_oom_escalate_gpu.py +0 -0
  491. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_opd.py +0 -0
  492. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_opd_limits.py +0 -0
  493. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_opd_multiturn_eos_boundary.py +0 -0
  494. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_opd_multiturn_failure_exit.py +0 -0
  495. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_opd_replay_guard.py +0 -0
  496. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_opd_resume_safety.py +0 -0
  497. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_opd_train.py +0 -0
  498. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_orchestrator_flash.py +0 -0
  499. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_packing.py +0 -0
  500. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_packing_coverage.py +0 -0
  501. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_parasail_teacher.py +0 -0
  502. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_poll_helpers.py +0 -0
  503. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_preflight.py +0 -0
  504. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_projects.py +0 -0
  505. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_prompt_budget.py +0 -0
  506. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_provider_preflight_coverage.py +0 -0
  507. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_provider_routing.py +0 -0
  508. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_provider_teardown_robustness.py +0 -0
  509. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_providers_symmetry.py +0 -0
  510. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_realized_cost.py +0 -0
  511. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_repo_cleanup.py +0 -0
  512. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_resolve_params_b.py +0 -0
  513. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_resume_on_retry.py +0 -0
  514. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_rl_train.py +0 -0
  515. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_rollout_samples.py +0 -0
  516. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_runpod_api_delete.py +0 -0
  517. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_runpod_key_fingerprint.py +0 -0
  518. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_runpod_key_waterfall.py +0 -0
  519. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_runtime_capsule.py +0 -0
  520. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_serve.py +0 -0
  521. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_serve_reasoning_content.py +0 -0
  522. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_server_app_coverage.py +0 -0
  523. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_server_auth_singleflight.py +0 -0
  524. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_server_billing.py +0 -0
  525. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_server_checkpoints_coverage.py +0 -0
  526. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_server_db.py +0 -0
  527. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_server_locks_coverage.py +0 -0
  528. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_server_standalone.py +0 -0
  529. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_serving_context_preflight.py +0 -0
  530. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_serving_contract.py +0 -0
  531. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_serving_schema_coverage.py +0 -0
  532. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_sft_chunked_nll.py +0 -0
  533. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_sft_example_selection.py +0 -0
  534. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_sft_gc_off.py +0 -0
  535. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_sft_max_context.py +0 -0
  536. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_sft_startup_block.py +0 -0
  537. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_sft_train.py +0 -0
  538. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_sft_workload.py +0 -0
  539. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_step_floor.py +0 -0
  540. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_step_metrics.py +0 -0
  541. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_step_timing.py +0 -0
  542. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_structured_outputs.py +0 -0
  543. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_teacher_broker.py +0 -0
  544. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_teacher_encoding_contract.py +0 -0
  545. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_terminal_artifacts.py +0 -0
  546. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_thinking_config.py +0 -0
  547. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_train_context_preflight.py +0 -0
  548. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_training_controls.py +0 -0
  549. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_type_comment_prose.py +0 -0
  550. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_vast_api.py +0 -0
  551. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_vast_api_coverage.py +0 -0
  552. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_vast_offers.py +0 -0
  553. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_vast_provider_coverage.py +0 -0
  554. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_vast_runner.py +0 -0
  555. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_verified_revisions.py +0 -0
  556. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_verifiers.py +0 -0
  557. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_verl_checkpoint_export.py +0 -0
  558. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_verl_child_plugins.py +0 -0
  559. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_verl_silence_watchdog.py +0 -0
  560. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_version.py +0 -0
  561. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_vl_warmstart_adapter_keys.py +0 -0
  562. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_vram_architecture.py +0 -0
  563. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_wandb_link.py +0 -0
  564. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_wandb_naming.py +0 -0
  565. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_warmstart_adapter_download.py +0 -0
  566. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_warmstart_error_attribution.py +0 -0
  567. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_weight_cache.py +0 -0
  568. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_worker_dryrun.py +0 -0
  569. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_worker_hardexit.py +0 -0
  570. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_worker_image.py +0 -0
  571. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_worker_init_heartbeat.py +0 -0
  572. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_worker_stack.py +0 -0
  573. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_worker_thinking.py +0 -0
  574. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_workflow_contracts.py +0 -0
  575. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_workload_profile.py +0 -0
  576. {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.59}/tests/test_zero2_sharding_gate.py +0 -0
@@ -21,6 +21,17 @@ This file starts at 1.1.35. Earlier releases are not reconstructed here; use
21
21
 
22
22
  ### Changed
23
23
 
24
+ - A RunPod attempt's stall window is now measured from evidence timestamps rather than from when
25
+ the control plane happened to look at it. The window was seeded from the moment polling started
26
+ and was reset again by the first status read, and a heartbeat was credited at the time it was
27
+ read rather than the time it was written. Every one of those is a wall-clock reading, so each
28
+ reattach handed a worker that was already wedged a complete fresh setup window, and a supervisor
29
+ that reattached repeatedly could keep a dead worker on a paid GPU until the run's wall deadline.
30
+ The window is now anchored to the persisted launch, a heartbeat is credited at its own timestamp
31
+ clamped to that launch, and only a genuine status transition counts as progress. Instance
32
+ polling (Vast/Lambda) already worked this way; this brings RunPod onto the same rule. A job that
33
+ is still queued is unaffected: the capacity wait keeps its own exemption, so a worker granted
34
+ late still gets its full cold-start budget.
24
35
  - An attempt's terminal artifacts (its strict marker plus `metrics.json`) are now interpreted by
25
36
  one shared protocol instead of being decoded separately by live instance polling and by each
26
37
  recovery path. The two decoders disagreed about identical bytes. A marker that could not be tied
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: freesolo-flash-dev
3
- Version: 1.2.53
3
+ Version: 1.2.59
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)
@@ -18,6 +18,7 @@ from flash.providers._lifecycle.deadline import (
18
18
  from flash.providers._lifecycle.poll import (
19
19
  PollErrorTracker,
20
20
  _attempt_int,
21
+ heartbeat_progress_ts,
21
22
  is_training_heartbeat,
22
23
  make_say,
23
24
  surface_heartbeat,
@@ -547,6 +548,20 @@ def _classify_queue_state(
547
548
  return None
548
549
 
549
550
 
551
+ def _progress_ts(context: _PollContext, hb_key: tuple) -> float:
552
+ """The progress this heartbeat proves: its own ts, clamped to [launch, now].
553
+
554
+ The companion ``fresh`` flag is deliberately dropped. Its attempt half is already decided by the
555
+ caller, which returns early on any heartbeat that is not this attempt's, and its ts half is
556
+ already expressed in the clamp: a heartbeat stamped before launch cannot describe work this
557
+ attempt did, so it is worth exactly the launch anchor and no more. What remains is the
558
+ unusable-ts case, where the helper falls back to now; that matches the previous behaviour of
559
+ treating an untimestamped heartbeat as present-tense progress.
560
+ """
561
+ ts, _fresh = heartbeat_progress_ts(hb_key, context.launch_ts, context.current_attempt)
562
+ return ts
563
+
564
+
550
565
  def _update_heartbeat(context: _PollContext, state: _PollState) -> None:
551
566
  new_key, stage = surface_heartbeat(context.heartbeat_reader, state.last_hb_key, context.say)
552
567
  if new_key == state.last_hb_key:
@@ -575,17 +590,29 @@ def _update_heartbeat(context: _PollContext, state: _PollState) -> None:
575
590
  hb_ts = new_key[2]
576
591
  hb_step = new_key[1]
577
592
  is_training_hb = is_training_heartbeat(stage, hb_step)
593
+ # Credit the heartbeat's OWN timestamp, clamped to [launch, now], never the time we happened to
594
+ # read it. A heartbeat written long before a reattach and only seen now describes progress that
595
+ # already happened; paying it out at read time hands a wedged worker a full fresh stall window
596
+ # on every reattach. `_progress_ts` returns that clamped value, deliberately distinct from the
597
+ # raw `hb_ts` above, which stays the uploaded-ts bookkeeping the advance checks below compare.
598
+ # A heartbeat with no usable ts still clamps to now, preserving the existing behaviour that an
599
+ # untimestamped heartbeat counts as progress. It is computed only where it is used: this loop's
600
+ # clock is observable through `_jobs.time.time`, so an unused read would be a visible side effect.
601
+ #
602
+ # heartbeat ordering is independent of other progress sources. a queue exemption or status
603
+ # transition may already have advanced `last_progress` beyond this heartbeat's timestamp, so
604
+ # preserve the newer stall anchor while updating heartbeat-specific bookkeeping.
578
605
  if hb_attempt > state.last_hb_attempt:
579
606
  # fresh attempt: reset ts baseline and re-derive seen_training_hb so cold-start grace rearms.
580
607
  state.last_hb_attempt = hb_attempt
581
608
  state.last_hb_ts = hb_ts or 0.0
582
- state.last_progress = _jobs.time.time()
609
+ state.last_progress = max(state.last_progress, _progress_ts(context, new_key))
583
610
  state.seen_training_hb = is_training_hb
584
611
  elif hb_attempt == state.last_hb_attempt and (hb_ts is None or hb_ts > state.last_hb_ts):
585
612
  # gate progress on ts advancing: a stale late upload must not buy a fresh stall window.
586
613
  if hb_ts is not None:
587
614
  state.last_hb_ts = hb_ts
588
- state.last_progress = _jobs.time.time()
615
+ state.last_progress = max(state.last_progress, _progress_ts(context, new_key))
589
616
  if is_training_hb:
590
617
  state.seen_training_hb = True
591
618
 
@@ -702,7 +729,13 @@ def poll_job(
702
729
  last_hb_ts=0.0,
703
730
  # -1 sentinel < any real attempt; gates out prior-attempt leftover heartbeats
704
731
  last_hb_attempt=-1,
705
- last_progress=_jobs.time.time(),
732
+ # Seed from the persisted LAUNCH, not this poll's start. A reattach has been billing since
733
+ # launch, so a worker already wedged before we attached must not be handed a fresh setup
734
+ # window by the mere act of looking at it -- that is what let a restart loop keep a dead
735
+ # worker alive to the absolute deadline. For a job queued from the start this value is
736
+ # overwritten anyway by the queued exemption in `_classify_stall`, which re-anchors on every
737
+ # pre-grant poll; it is the ALREADY-PLACED job at poll start where the difference is real.
738
+ last_progress=launch_ts,
706
739
  seen_training_hb=False,
707
740
  last_health_probe=0.0,
708
741
  unhealthy_timer=_jobs.GraceTimer(),
@@ -741,8 +774,13 @@ def poll_job(
741
774
  state.ever_saw_worker = True
742
775
  if status != state.last_status:
743
776
  say(f"job {handle.job_id}: {status}")
777
+ # A genuine TRANSITION is progress, so it moves the clock. The FIRST observation is not a
778
+ # transition -- `last_status` simply starts unset -- and crediting it would throw away the
779
+ # launch anchor on poll one, which is exactly how a delayed reattach used to win back a
780
+ # whole setup window before any evidence of progress had been seen.
781
+ if state.last_status is not None:
782
+ state.last_progress = _jobs.time.time()
744
783
  state.last_status = status
745
- state.last_progress = _jobs.time.time()
746
784
  terminal = _classify_terminal_status(context, state, provider_status, status)
747
785
  if terminal is not None:
748
786
  return terminal
@@ -28,7 +28,6 @@ from flash.adapters.artifacts import MAX_ATTEMPT_ID as MAX_ATTEMPT_ID
28
28
  # moved code reads them back through it. an autofix that drops them breaks those tests.
29
29
  from flash.core.catalog import ModelInfo, resolve_model # noqa: F401
30
30
  from flash.core.spec import ( # noqa: F401
31
- _DROPPED_TOP_LEVEL_KEYS,
32
31
  MANAGED_GPU_KEYS,
33
32
  TRAINER_BACKEND,
34
33
  GpuSpec,
@@ -124,19 +123,11 @@ def _adapter_ref_for_status(status: RunStatus) -> str | None:
124
123
  raw_worker = (status.effective_preparation or {}).get("worker_spec")
125
124
  if not raw_worker:
126
125
  return None
127
- # a workload-profile run recorded before #1095 removed the profile job has a managed hf_repo but
128
- # never produced an adapter. its worker payload still carries the marker, which JobSpec.from_dict
129
- # now drops, so read it off the raw record rather than reviving the field.
130
- if isinstance(raw_worker, dict) and raw_worker.get("workload_profile_kind"):
131
- return None
132
126
  try:
133
127
  spec = _internal_spec_from_status(status)
134
128
  except Exception:
135
- # a status json written by an OLDER plane can carry since-removed spec keys (e.g.
136
- # ``gpu.exact_type`` pre-#670), and stored run records are never rewritten. JobSpec.from_dict
137
- # is strict, so parsing raises -- and one such record would 500 the whole runs list. same
138
- # operational tolerance as _runstatus_from_json: the record stays readable, it just shows no
139
- # adapter ref (its spec cannot name one we could resolve).
129
+ # an unparseable stored spec must not 500 the whole runs list: the record stays readable, it
130
+ # just shows no adapter ref (its spec cannot name one we could resolve).
140
131
  return None
141
132
  if not spec.train.hf_repo:
142
133
  return None
@@ -805,13 +796,11 @@ from flash.runner.preparation import ( # noqa: E402,F401
805
796
  _preparation_digest,
806
797
  _prepare_init_from_adapter,
807
798
  _prepare_init_from_adapter_inner,
808
- _prepared_before_public_alpha,
809
799
  _profile_producer_version,
810
800
  _require_pinned_profile_environment,
811
801
  _require_sft_workload_profile,
812
802
  _require_supported_adapter_continuation,
813
803
  _resolve_model_revision,
814
- _stored_rollout_batch_spelling,
815
804
  _validate_effective_spec,
816
805
  _warmstart_source_is_authorized,
817
806
  )
@@ -88,47 +88,6 @@ def _spec_pinned_to_horizon(spec, steps: int):
88
88
  return _replace(spec, train=_replace(spec.train, max_steps=max(1, int(steps))))
89
89
 
90
90
 
91
- def _spec_with_legacy_pool_horizon(spec):
92
- """``spec`` with a legacy ``[environment.params] max_examples`` restated as ``[train]``, for PRORATION ONLY.
93
-
94
- A run accepted before flash stopped reading that key was quoted from it, and cancelling it now
95
- has to answer "what fraction of the accepted work happened" -- a question about the OLD work
96
- model, not about what flash would quote today. Without this the full-work reprice raises (no
97
- stated pool) while the partial pins ``max_steps`` and prices the uncapped batch, so the fraction
98
- dies and the charge falls through to the quote cap: a legacy 10-step run cancelled after ONE
99
- step bills 100% of its quote instead of 10%.
100
-
101
- Restating it under ``[train]`` reproduces the horizon the accepted quote was computed from,
102
- which is exactly what the ratio needs. Safe here in a way it is not at submit: both sides of
103
- ``partial / full`` are repriced through this same shape, so the value only ever sets a fraction
104
- between two numbers that share it -- it never becomes a price a customer is quoted, and the
105
- result stays capped by the quote they accepted. Specs that state ``[train] max_examples`` or
106
- ``max_steps`` already have a horizon and are returned untouched.
107
- """
108
- from dataclasses import replace as _replace
109
-
110
- if getattr(spec, "algorithm", "") not in ("grpo", "opd"):
111
- return spec
112
- train = getattr(spec, "train", None)
113
- if train is None or int(getattr(train, "max_examples", 0) or 0) > 0:
114
- return spec
115
- if int(getattr(train, "max_steps", 0) or 0) > 0:
116
- return spec
117
- params = getattr(getattr(spec, "environment", None), "params", {}) or {}
118
- if not isinstance(params, dict):
119
- return spec
120
- try:
121
- legacy_pool = int(params.get("max_examples") or 0)
122
- except (TypeError, ValueError, OverflowError):
123
- # same unreadable-value cases _env_max_examples guarded: `int(inf)` raises OverflowError,
124
- # `int(nan)` ValueError. an unreadable pool is no horizon, so leave the spec alone and let
125
- # the caller's own unpriceable-fraction branch handle it.
126
- return spec
127
- if legacy_pool <= 0:
128
- return spec
129
- return _replace(spec, train=_replace(train, max_examples=legacy_pool))
130
-
131
-
132
91
  def charge_usd_for_spec(
133
92
  spec,
134
93
  *,
@@ -303,9 +262,8 @@ def cancelled_charge_usd(
303
262
  # billing retry predicate (cost_usd > 0) can never settle, silently stranding the run
304
263
  # unbilled, so the fallback propagates and the caller records the pricing failure.
305
264
  return float(fallback)
306
- prorated_spec = _spec_with_legacy_pool_horizon(spec)
307
265
  partial = runner.charge_usd_for_spec(
308
- prorated_spec,
266
+ spec,
309
267
  steps=n,
310
268
  fallback=float("nan"),
311
269
  provider=provider,
@@ -313,7 +271,7 @@ def cancelled_charge_usd(
313
271
  gpu_count=gpu_count,
314
272
  )
315
273
  full = runner.charge_usd_for_spec(
316
- prorated_spec,
274
+ spec,
317
275
  fallback=float("nan"),
318
276
  provider=provider,
319
277
  gpu_type=gpu_type,
@@ -16,9 +16,7 @@ import json
16
16
  import os
17
17
  import re
18
18
  from dataclasses import replace
19
- from typing import Any
20
19
 
21
- from flash.core.catalog import normalize_algorithm, samples_on_policy
22
20
  from flash.core.spec import JobSpec
23
21
 
24
22
 
@@ -298,129 +296,17 @@ def _mark_warmstart_source(worker_spec: JobSpec, child_run_id: str) -> None:
298
296
  )
299
297
 
300
298
 
301
- def _prepared_before_public_alpha(raw_public: object) -> bool:
302
- """True when this run's PERSISTED public spec predates ``lora_alpha`` becoming authorable.
303
-
304
- The discriminator is the stored bytes, not this build's serialization: a snapshot prepared
305
- before the change hashed a public spec with no alpha key, and its digest can only be reproduced
306
- the same way. status.spec is never rewritten, so this answer is stable for the run's life.
307
-
308
- A warm-start spec is excluded even though it also omits alpha -- to_dict() strips rank and alpha
309
- for those in every version, so absence there says nothing about when the run was prepared, and
310
- treating it as legacy would drop a binding that costs nothing to keep.
311
- """
312
- if not isinstance(raw_public, dict):
313
- return False
314
- train = raw_public.get("train")
315
- if not isinstance(train, dict) or "lora_alpha" in train:
316
- return False
317
- return not train.get("init_from_adapter")
318
-
319
-
320
- _ROLLOUT_BATCH_KEYS = ("batch_size", "prompts_per_step")
321
-
322
-
323
- def _stored_rollout_batch_spelling(raw_spec: object) -> dict[str, Any] | None:
324
- """How a PERSISTED rollout spec spelled its optimizer batch, or None if it is not one.
325
-
326
- Same discriminator style as ``_prepared_before_public_alpha``: the answer comes from the stored
327
- bytes, which are never rewritten, so it is stable for the run's life.
328
-
329
- ``JobSpec.from_dict`` MOVES the pre-1.1.43 ``batch_size`` onto ``prompts_per_step`` when
330
- reparsing, so rehashing a persisted spec with today's parse can produce different bytes than
331
- were hashed at persist time -- failing integrity validation for exactly the warm-start grpo/opd
332
- runs this migration exists to rescue.
333
-
334
- Both keys are reported, rather than just the value there is to migrate. Reporting only the
335
- latter conflates snapshots that have nothing to move but still change shape: a mixed-version
336
- payload storing both names (the migration drops the old one, so the stored ``batch_size`` still
337
- has to be rehashed), one whose legacy value is non-positive (discarded by the parser), and a
338
- modern payload (nothing to do). Replaying the stored spelling covers all of them uniformly.
339
-
340
- A key merely holding null reports None; a key genuinely OMITTED is omitted from the reading too,
341
- because the two hash differently. Every digest is taken over a serialized ``JobSpec``, which
342
- emits both names, so a null was really hashed as null -- while 1.1.40 predates
343
- ``prompts_per_step`` entirely and hashed no such key. Each half's reading therefore carries its
344
- OWN absence rather than sharing one flag: after a re-persist the worker half is rewritten in the
345
- modern shape while ``status.spec`` keeps the legacy one, so the halves genuinely disagree about
346
- which keys exist and a single flag would misdescribe one of them.
347
-
348
- This is not a way to forge a batch: the replayed values are the STORED ones, and the digest they
349
- are compared against was computed over the ORIGINAL ones, so any tampering still mismatches.
350
-
351
- Only a rollout algorithm is eligible: for sft ``batch_size`` is the current, un-migrated name,
352
- which ``from_dict`` leaves alone.
353
- """
354
- if not isinstance(raw_spec, dict):
355
- return None
356
- if not samples_on_policy(normalize_algorithm(str(raw_spec.get("algorithm") or ""))):
357
- return None
358
- train = raw_spec.get("train")
359
- if not isinstance(train, dict):
360
- return None
361
- stored = {key: train.get(key) for key in _ROLLOUT_BATCH_KEYS}
362
- # the 1.1.40 shape, read off the bytes themselves: it carried the old name and no new one.
363
- # a payload omitting BOTH says nothing about when it was written, and the serializer always
364
- # emits both -- so treating that as absence would drop a key that WAS hashed.
365
- if "batch_size" in train and "prompts_per_step" not in train:
366
- del stored["prompts_per_step"]
367
- return stored
368
-
369
-
370
- def _restore_rollout_batch_spelling(payload: dict, stored: dict | None) -> None:
371
- """Put the optimizer-batch keys back exactly as the stored payload hashed them.
372
-
373
- A key absent from ``stored`` was absent from the hashed bytes, so it is removed rather than
374
- written -- that is the 1.1.40 shape, which predates ``prompts_per_step``.
375
- """
376
- if stored is None:
377
- return
378
- train = payload.get("train")
379
- if not isinstance(train, dict):
380
- return
381
- for key in _ROLLOUT_BATCH_KEYS:
382
- if key in stored:
383
- train[key] = stored[key]
384
- else:
385
- train.pop(key, None)
386
-
387
-
388
299
  def _preparation_digest(
389
300
  public_spec: JobSpec,
390
301
  worker_spec: JobSpec,
391
302
  adapter_identity: dict | None,
392
- *,
393
- legacy_keys: dict | None = None,
394
- legacy_public_keys: dict | None = None,
395
- legacy_public_alpha: bool = False,
396
- stored_rollout_batch: dict | None = None,
397
- stored_public_rollout_batch: dict | None = None,
398
303
  ) -> str:
399
304
  worker_payload = worker_spec.to_internal_dict()
400
305
  public_payload = public_spec.to_dict()
401
- # the rollout optimizer batch was renamed `batch_size` -> `prompts_per_step`, and from_dict now
402
- # MOVES it when reparsing a persisted spec. Rehash under the spelling the snapshot actually
403
- # stored -- including a key it did not have -- so a spec written before or across the rename
404
- # still reproduces its digest. Same reason as the omissions and restorations below.
405
- #
406
- # Each half is restored from ITS OWN stored payload, exactly like legacy_keys vs
407
- # legacy_public_keys below. Feeding the worker's spelling to both would overwrite whatever the
408
- # public payload held before hashing -- and since the parse DROPS a superseded `batch_size`,
409
- # `_validate_effective_spec` cannot see it either, so a tampered public value would be erased
410
- # rather than caught. The two halves legitimately differ (the public spec is a stripped view),
411
- # so they cannot share one reading -- including which keys they carry at all, which is why each
412
- # reading holds its own absence instead of a shared flag. Re-persisting rewrites the worker half
413
- # in the modern shape and leaves `status.spec` legacy, so from then on the halves disagree.
414
- _restore_rollout_batch_spelling(worker_payload, stored_rollout_batch)
415
- _restore_rollout_batch_spelling(public_payload, stored_public_rollout_batch)
416
- # ``[environment] pip`` became user-authorable, so to_dict() now emits it where it used to be
417
- # stripped, and a pre-upgrade snapshot hashed an environment with no pip key at all. Dropping it
418
- # when empty reproduces those bytes without needing to know when the run was prepared: absent
419
- # and empty are the same install, so they must hash alike. An authored pip is non-empty and
420
- # stays bound, so tampering with the persisted value is still caught.
306
+ # absent and empty pip are the same install, so they must hash alike.
421
307
  if not public_payload["environment"].get("pip"):
422
308
  public_payload["environment"].pop("pip", None)
423
- # omit empty fields so existing version-1 snapshots keep their historical digest.
309
+ # omit empty managed fields so the hashed payload carries only what the run actually set.
424
310
  for key in (
425
311
  "model_revision_auto",
426
312
  "gpu_count_auto",
@@ -430,34 +316,6 @@ def _preparation_digest(
430
316
  ):
431
317
  if not worker_payload.get(key):
432
318
  worker_payload.pop(key, None)
433
- # Restore since-removed keys the STORED payload carried, for the same reason as the omissions
434
- # above: the digest has to reproduce the bytes that were hashed, not today's serialization. A
435
- # pre-upgrade snapshot hashed `model_policy` in (to_internal_dict was asdict, so it emitted the
436
- # defaulted value), and the field no longer exists -- so rehashing without it mismatches and a
437
- # still-valid warm-start or workload-profile run fails integrity validation on recovery. Only
438
- # keys registered as historical public removals are honoured. Any field the dataclass still
439
- # defines already comes from worker_spec, so replaying its identical stored value cannot forge it.
440
- for key, value in (legacy_keys or {}).items():
441
- if key in _runner()._DROPPED_TOP_LEVEL_KEYS:
442
- worker_payload[key] = value
443
- # a dropped key that was USER-AUTHORABLE was hashed on the public side too, not just the worker
444
- # side. model_policy never was, so restoring only the worker payload was enough for it;
445
- # model_revision and worker_env were, so a pre-upgrade public_spec carried them and the digest
446
- # cannot reproduce without them.
447
- for key, value in (legacy_public_keys or {}).items():
448
- if key in _runner()._DROPPED_TOP_LEVEL_KEYS:
449
- public_payload[key] = value
450
- # ``lora_alpha`` became user-authorable, so to_dict() now emits it for non-warm-start runs. A
451
- # snapshot prepared BEFORE that change hashed a public spec without alpha, so rehashing it with
452
- # alpha would fail a still-valid run's integrity check on recovery -- same reason as the
453
- # omissions and restorations above. That omission is scoped to those legacy snapshots only: a
454
- # digest created from here on binds the public alpha, so tampering with the persisted public
455
- # value is caught. Without that binding the two halves can disagree silently, because
456
- # _runner()._validate_effective_spec() excludes lora_alpha from its structural comparison (the worker's
457
- # warm-start-inherited alpha legitimately differs from the public one), leaving the digest as
458
- # the only thing that could cover it.
459
- if legacy_public_alpha:
460
- public_payload["train"].pop("lora_alpha", None)
461
319
  payload = {
462
320
  "version": 1,
463
321
  "public_spec": public_payload,
@@ -488,15 +346,12 @@ def _validate_effective_spec(public_spec: JobSpec, worker_spec: JobSpec) -> None
488
346
  "workload_profile",
489
347
  ):
490
348
  effective[managed_top] = public.get(managed_top)
491
- # the pin value is stripped from every new public spec. a runner-assigned pin is asymmetric by
492
- # design, as is an authored pin inherited by a new warm-start child after the public key's removal.
493
- # exclude those two cases only. a historical authored source still carries its public revision and
494
- # remains structurally compared. both asymmetric shapes are digest-protected: the marker triggers
495
- # verification for auto pins, and every warm start verifies its complete preparation snapshot.
496
- if not public.get("model_revision") and (
497
- worker_spec.model_revision_auto or public.get("train", {}).get("init_from_adapter")
498
- ):
499
- effective["model_revision"] = public.get("model_revision")
349
+ # the pin value is stripped from EVERY public spec (`to_dict` drops it), so the worker half
350
+ # legitimately carries a revision the public half cannot: a runner-assigned pin, or an authored
351
+ # pin a warm-start child inherited. the asymmetry is therefore unconditional and excluded here.
352
+ # it stays digest-protected: the auto marker triggers digest verification, and every warm start
353
+ # verifies its complete preparation snapshot.
354
+ effective["model_revision"] = public.get("model_revision")
500
355
  public_train = dict(public["train"])
501
356
  effective_train = dict(effective["train"])
502
357
  public_ref = public_train.get("init_from_adapter") or ""