freesolo-flash-dev 1.2.58__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 (575) hide show
  1. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/CHANGELOG.md +11 -0
  2. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/PKG-INFO +1 -1
  3. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/runpod/job_execution.py +42 -4
  4. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/pyproject.toml +2 -2
  5. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_jobs.py +207 -13
  6. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/uv.lock +1 -1
  7. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/.dockerignore +0 -0
  8. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/.env.example +0 -0
  9. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/.github/CODEOWNERS +0 -0
  10. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  11. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  12. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  13. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  14. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/.github/dependabot.yml +0 -0
  15. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/.github/workflows/auto-rebake.yml +0 -0
  16. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/.github/workflows/bake-kernel-cache.yml +0 -0
  17. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/.github/workflows/ci.yml +0 -0
  18. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/.github/workflows/main-source-guard.yml +0 -0
  19. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/.github/workflows/notify-tests-repo.yml +0 -0
  20. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/.github/workflows/publish-dev.yml +0 -0
  21. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/.github/workflows/publish-image.yml +0 -0
  22. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/.github/workflows/publish.yml +0 -0
  23. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/.github/workflows/version-parity.yml +0 -0
  24. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/.github/workflows/worker-image.yml +0 -0
  25. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/.gitignore +0 -0
  26. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/CODE_OF_CONDUCT.md +0 -0
  27. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/CONTRIBUTING.md +0 -0
  28. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/Dockerfile +0 -0
  29. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/Dockerfile.worker +0 -0
  30. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/LICENSE +0 -0
  31. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/NOTICE +0 -0
  32. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/README.md +0 -0
  33. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/SECURITY.md +0 -0
  34. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/SELF_HOSTING.md +0 -0
  35. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/build/kernel_cache/.gitignore +0 -0
  36. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/build/kernel_cache/.keep +0 -0
  37. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/deploy/infisical/README.md +0 -0
  38. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/deploy/infisical/entrypoint.sh +0 -0
  39. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/docker/Dockerfile.kernelcache +0 -0
  40. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/docker/Dockerfile.kernelcache.relayer +0 -0
  41. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/docker/bake_kernel_cache.py +0 -0
  42. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/docker/bake_pod_entry.py +0 -0
  43. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/docker/extract_cudart_fix.py +0 -0
  44. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/docker/kernel_fingerprint.py +0 -0
  45. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/docker/make_rp_handler.py +0 -0
  46. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/__init__.py +0 -0
  47. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/_internal/__init__.py +0 -0
  48. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/_internal/channel.py +0 -0
  49. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/_internal/diagnostics.py +0 -0
  50. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/_internal/fileio.py +0 -0
  51. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/_internal/logging.py +0 -0
  52. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/_internal/paths.py +0 -0
  53. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/adapters/__init__.py +0 -0
  54. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/adapters/artifacts.py +0 -0
  55. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/adapters/fused_experts.py +0 -0
  56. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/adapters/lora_rank.py +0 -0
  57. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/cli/__init__.py +0 -0
  58. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/cli/__main__.py +0 -0
  59. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/cli/commands/__init__.py +0 -0
  60. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/cli/commands/deploy.py +0 -0
  61. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/cli/commands/env/__init__.py +0 -0
  62. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/cli/commands/env/episode.py +0 -0
  63. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/cli/commands/env/eval.py +0 -0
  64. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/cli/commands/env/eval_args.py +0 -0
  65. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/cli/commands/env/imports.py +0 -0
  66. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/cli/commands/env/list.py +0 -0
  67. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/cli/commands/env/push.py +0 -0
  68. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/cli/commands/env/retained.py +0 -0
  69. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/cli/commands/env/setup.py +0 -0
  70. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/cli/commands/env/test.py +0 -0
  71. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/cli/commands/env/test_evaluations.py +0 -0
  72. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/cli/commands/env/test_params.py +0 -0
  73. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/cli/commands/env/test_warnings.py +0 -0
  74. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/cli/commands/prompt_budget.py +0 -0
  75. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/cli/commands/traces.py +0 -0
  76. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/cli/commands/train_cost.py +0 -0
  77. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/cli/scaffold/TRAINING.md +0 -0
  78. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/cli/scaffold/__init__.py +0 -0
  79. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/cli/ui/__init__.py +0 -0
  80. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/cli/ui/cost.py +0 -0
  81. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/cli/ui/env_panels.py +0 -0
  82. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/cli/ui/heartbeat.py +0 -0
  83. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/cli/ui/render.py +0 -0
  84. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/cli/ui/tables.py +0 -0
  85. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/cli/ui/tty.py +0 -0
  86. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/client/__init__.py +0 -0
  87. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/client/config.py +0 -0
  88. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/client/freesolo_api.py +0 -0
  89. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/client/http.py +0 -0
  90. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/client/runtime_secrets.py +0 -0
  91. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/client/shapes.py +0 -0
  92. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/client/specs.py +0 -0
  93. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/client/streaming.py +0 -0
  94. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/content/__init__.py +0 -0
  95. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/content/multimodal.py +0 -0
  96. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/content/structured_outputs.py +0 -0
  97. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/content/thinking.py +0 -0
  98. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/core/__init__.py +0 -0
  99. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/core/catalog.py +0 -0
  100. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/core/spec.py +0 -0
  101. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/core/spec_persistence.py +0 -0
  102. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/cost/__init__.py +0 -0
  103. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/cost/analytical.py +0 -0
  104. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/cost/facts.py +0 -0
  105. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/cost/spec.py +0 -0
  106. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/cost/types.py +0 -0
  107. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/__init__.py +0 -0
  108. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/plan/__init__.py +0 -0
  109. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/plan/kv_sizing.py +0 -0
  110. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/plan/model_config_probe.py +0 -0
  111. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/plan/prompt_budget.py +0 -0
  112. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/plan/recipe.py +0 -0
  113. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/plan/steps.py +0 -0
  114. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/plan/vram.py +0 -0
  115. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/profiling/__init__.py +0 -0
  116. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/profiling/dataset_profile.py +0 -0
  117. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/profiling/reasoning_render.py +0 -0
  118. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/profiling/sft_workload.py +0 -0
  119. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/profiling/tokenizer.py +0 -0
  120. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/profiling/workload_profile.py +0 -0
  121. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/result/__init__.py +0 -0
  122. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/result/accounting.py +0 -0
  123. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/result/rollout_samples.py +0 -0
  124. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/__init__.py +0 -0
  125. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/__main__.py +0 -0
  126. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/backend_common.py +0 -0
  127. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/entry/__init__.py +0 -0
  128. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/entry/opd.py +0 -0
  129. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/entry/rl.py +0 -0
  130. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/entry/sft.py +0 -0
  131. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/io/__init__.py +0 -0
  132. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/io/heartbeat.py +0 -0
  133. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/io/hf.py +0 -0
  134. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/io/prefetch.py +0 -0
  135. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/io/wandb_log.py +0 -0
  136. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/model/__init__.py +0 -0
  137. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/model/adapter.py +0 -0
  138. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/model/chatml_mask.py +0 -0
  139. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/model/decoding.py +0 -0
  140. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/model/lora.py +0 -0
  141. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/model/packing.py +0 -0
  142. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/opd_train.py +0 -0
  143. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/opd_train_runner.py +0 -0
  144. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/perf/__init__.py +0 -0
  145. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/perf/diagnostics.py +0 -0
  146. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/perf/lifecycle.py +0 -0
  147. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/perf/liger.py +0 -0
  148. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/perf/memory.py +0 -0
  149. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/rl_train.py +0 -0
  150. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/rl_train_runner.py +0 -0
  151. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/runtime/__init__.py +0 -0
  152. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/runtime/kernel_warmup.py +0 -0
  153. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/runtime/pkg_proxy.py +0 -0
  154. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/runtime/rng.py +0 -0
  155. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/score_batcher.py +0 -0
  156. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/sft_train.py +0 -0
  157. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/sft_train_runner.py +0 -0
  158. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/teacher/__init__.py +0 -0
  159. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/teacher/client.py +0 -0
  160. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/teacher/encoding.py +0 -0
  161. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/teacher/tokenizer_align.py +0 -0
  162. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/__init__.py +0 -0
  163. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/core/__init__.py +0 -0
  164. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/core/checkpoint_lifecycle.py +0 -0
  165. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/core/child/__init__.py +0 -0
  166. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/core/child/glue.py +0 -0
  167. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/core/child/runtime.py +0 -0
  168. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/core/step_timing.py +0 -0
  169. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/finalize.py +0 -0
  170. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/opd/__init__.py +0 -0
  171. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/opd/batching.py +0 -0
  172. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/opd/bridge.py +0 -0
  173. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/opd/child/__init__.py +0 -0
  174. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/opd/child/bridge.py +0 -0
  175. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/opd/child/entry.py +0 -0
  176. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/opd/child/multiturn.py +0 -0
  177. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/opd/child/plugin.py +0 -0
  178. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/opd/child/replay_guard.py +0 -0
  179. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/opd/child/runtime.py +0 -0
  180. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/opd/child/structured.py +0 -0
  181. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/opd/failures.py +0 -0
  182. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/opd/gkd.py +0 -0
  183. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/opd/multiturn_validation.py +0 -0
  184. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/opd/overrides.py +0 -0
  185. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/opd/prompts.py +0 -0
  186. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/opd/reporting.py +0 -0
  187. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/opd/scoring.py +0 -0
  188. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/opd/state.py +0 -0
  189. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/opd/validation.py +0 -0
  190. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/rl/__init__.py +0 -0
  191. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/rl/checkpoints.py +0 -0
  192. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/rl/child/__init__.py +0 -0
  193. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/rl/child/entry.py +0 -0
  194. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/rl/child/multiturn.py +0 -0
  195. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/rl/child/patches.py +0 -0
  196. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/rl/child/plugin.py +0 -0
  197. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/rl/config.py +0 -0
  198. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/rl/inputs.py +0 -0
  199. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/rl/multi_turn.py +0 -0
  200. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/rl/reward_module.py +0 -0
  201. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/rl/scoring.py +0 -0
  202. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/rl/single_turn.py +0 -0
  203. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/rl/verl_config.py +0 -0
  204. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/sft/__init__.py +0 -0
  205. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/sft/checkpoints.py +0 -0
  206. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/sft/child/entry.py +0 -0
  207. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/sft/child/plugin.py +0 -0
  208. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/train/sft/config.py +0 -0
  209. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/verl/__init__.py +0 -0
  210. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/verl/capabilities.py +0 -0
  211. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/verl/checkpoints.py +0 -0
  212. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/verl/child_io.py +0 -0
  213. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/verl/diagnostics.py +0 -0
  214. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/verl/parallelism.py +0 -0
  215. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker/verl/parent_work.py +0 -0
  216. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/engine/worker_entrypoint.py +0 -0
  217. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/envs/__init__.py +0 -0
  218. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/envs/adapter.py +0 -0
  219. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/envs/base.py +0 -0
  220. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/envs/cache_security.py +0 -0
  221. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/envs/dataset_selection.py +0 -0
  222. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/envs/evaluations.py +0 -0
  223. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/envs/identity.py +0 -0
  224. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/envs/loader.py +0 -0
  225. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/envs/namespace_listing.py +0 -0
  226. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/envs/package/__init__.py +0 -0
  227. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/envs/package/limits.py +0 -0
  228. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/envs/package/unpack.py +0 -0
  229. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/envs/pull.py +0 -0
  230. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/__init__.py +0 -0
  231. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/_lifecycle/__init__.py +0 -0
  232. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/_lifecycle/auth.py +0 -0
  233. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/_lifecycle/bootstrap.py +0 -0
  234. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/_lifecycle/bootstrap_console.py +0 -0
  235. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/_lifecycle/bootstrap_pip.py +0 -0
  236. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/_lifecycle/bootstrap_secrets.py +0 -0
  237. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/_lifecycle/deadline.py +0 -0
  238. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/_lifecycle/host/__init__.py +0 -0
  239. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/_lifecycle/host/deadline_sleep.py +0 -0
  240. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/_lifecycle/host/failmark.py +0 -0
  241. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/_lifecycle/host/hostlog.py +0 -0
  242. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/_lifecycle/http.py +0 -0
  243. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/_lifecycle/instance.py +0 -0
  244. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/_lifecycle/poll.py +0 -0
  245. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/_lifecycle/poll_instance.py +0 -0
  246. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/_lifecycle/provider.py +0 -0
  247. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/_lifecycle/terminal_artifacts.py +0 -0
  248. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/_lifecycle/worker.py +0 -0
  249. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/allocator.py +0 -0
  250. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/artifacts/__init__.py +0 -0
  251. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/artifacts/hf.py +0 -0
  252. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/artifacts/preload_runpod.py +0 -0
  253. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/artifacts/weight_cache.py +0 -0
  254. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/base.py +0 -0
  255. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/fit_errors.py +0 -0
  256. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/lambda_/__init__.py +0 -0
  257. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/lambda_/api.py +0 -0
  258. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/lambda_/auth.py +0 -0
  259. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/lambda_/gpus.py +0 -0
  260. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/lambda_/jobs/__init__.py +0 -0
  261. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/lambda_/jobs/builders.py +0 -0
  262. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/lambda_/jobs/reap.py +0 -0
  263. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/lambda_/preflight.py +0 -0
  264. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/lambda_/pricing.py +0 -0
  265. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/preflight.py +0 -0
  266. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/realized.py +0 -0
  267. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/runpod/__init__.py +0 -0
  268. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/runpod/api.py +0 -0
  269. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/runpod/auth.py +0 -0
  270. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/runpod/cost.py +0 -0
  271. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/runpod/gpus.py +0 -0
  272. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/runpod/jobs.py +0 -0
  273. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/runpod/preflight.py +0 -0
  274. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/runpod/pricing.py +0 -0
  275. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/runpod/resources.py +0 -0
  276. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/runpod/serverless/__init__.py +0 -0
  277. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/runpod/serverless/endpoints.py +0 -0
  278. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/sharding.py +0 -0
  279. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/vast/__init__.py +0 -0
  280. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/vast/api.py +0 -0
  281. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/vast/auth.py +0 -0
  282. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/vast/jobs/__init__.py +0 -0
  283. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/vast/jobs/builders.py +0 -0
  284. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/vast/preflight.py +0 -0
  285. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/providers/vast/pricing.py +0 -0
  286. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/py.typed +0 -0
  287. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/runner/__init__.py +0 -0
  288. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/runner/artifacts.py +0 -0
  289. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/runner/attempts.py +0 -0
  290. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/runner/costs.py +0 -0
  291. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/runner/deadlines.py +0 -0
  292. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/runner/preparation.py +0 -0
  293. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/runner/reconciliation.py +0 -0
  294. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/runner/results/__init__.py +0 -0
  295. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/runner/results/checkpoints.py +0 -0
  296. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/runner/results/verified_revisions.py +0 -0
  297. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/runner/status.py +0 -0
  298. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/runner/submit.py +0 -0
  299. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/runner/supervise/__init__.py +0 -0
  300. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/runner/supervise/attach.py +0 -0
  301. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/runner/supervise/deploy.py +0 -0
  302. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/runner/supervise/lifecycle.py +0 -0
  303. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/runner/supervise/recovery.py +0 -0
  304. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/runner/supervise/retry_decision.py +0 -0
  305. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/runner/supervise/seed_submission.py +0 -0
  306. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/runner/supervise/transitions.py +0 -0
  307. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/runner/weight_cache.py +0 -0
  308. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/runtime_capsule/__init__.py +0 -0
  309. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/runtime_capsule/build.py +0 -0
  310. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/runtime_capsule/manifest.py +0 -0
  311. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/runtime_capsule/profiles.py +0 -0
  312. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/schema/__init__.py +0 -0
  313. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/schema/fields.py +0 -0
  314. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/serve/__init__.py +0 -0
  315. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/serve/adapter_check.py +0 -0
  316. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/serve/deploy.py +0 -0
  317. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/serve/errors.py +0 -0
  318. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/serve/export.py +0 -0
  319. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/serve/preflight.py +0 -0
  320. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/serve/responses.py +0 -0
  321. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/serve/streaming.py +0 -0
  322. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/serve/thinking.py +0 -0
  323. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/serve/urls.py +0 -0
  324. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/server/__init__.py +0 -0
  325. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/server/__main__.py +0 -0
  326. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/server/app.py +0 -0
  327. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/server/billing/__init__.py +0 -0
  328. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/server/billing/charges.py +0 -0
  329. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/server/billing/retry.py +0 -0
  330. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/server/domain/__init__.py +0 -0
  331. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/server/domain/checkpoints.py +0 -0
  332. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/server/domain/environment_registry.py +0 -0
  333. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/server/domain/envs.py +0 -0
  334. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/server/domain/projects.py +0 -0
  335. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/server/domain/reconcile.py +0 -0
  336. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/server/domain/repo_cleanup.py +0 -0
  337. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/server/domain/run_registry.py +0 -0
  338. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/server/domain/teacher_broker.py +0 -0
  339. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/server/domain/teacher_errors.py +0 -0
  340. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/server/domain/teacher_requests.py +0 -0
  341. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/server/platform/__init__.py +0 -0
  342. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/server/platform/auth.py +0 -0
  343. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/server/platform/db.py +0 -0
  344. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/server/platform/deps.py +0 -0
  345. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/server/platform/internal_client.py +0 -0
  346. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/server/platform/locks.py +0 -0
  347. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/server/platform/runtime.py +0 -0
  348. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/server/routes/__init__.py +0 -0
  349. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/server/routes/envs.py +0 -0
  350. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/server/routes/meta.py +0 -0
  351. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/server/routes/runs.py +0 -0
  352. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/server/routes/serving.py +0 -0
  353. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/server/routes/serving_completion.py +0 -0
  354. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/server/routes/serving_revisions.py +0 -0
  355. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/server/routes/serving_smoke.py +0 -0
  356. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/server/routes/teacher.py +0 -0
  357. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/teacher/__init__.py +0 -0
  358. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/teacher/limits.py +0 -0
  359. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/flash/teacher/retry_contract.py +0 -0
  360. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/scripts/build_dev_dist.py +0 -0
  361. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/scripts/check_file_size.py +0 -0
  362. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/scripts/check_function_size.py +0 -0
  363. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/scripts/check_verl_pin_exists.py +0 -0
  364. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/scripts/scrub_history.sh +0 -0
  365. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/__init__.py +0 -0
  366. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/_helpers/__init__.py +0 -0
  367. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/_helpers/profile.py +0 -0
  368. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/_helpers/runner.py +0 -0
  369. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/_helpers/specs.py +0 -0
  370. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/_helpers/teacher.py +0 -0
  371. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/_helpers/vast.py +0 -0
  372. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/conftest.py +0 -0
  373. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/fixtures/math_eval.jsonl +0 -0
  374. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/fixtures/math_train.jsonl +0 -0
  375. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/live/__init__.py +0 -0
  376. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/live/conftest.py +0 -0
  377. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/live/test_lambda_live.py +0 -0
  378. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/live/test_runpod_live.py +0 -0
  379. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/live/test_sft_thinking_render_live.py +0 -0
  380. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/live/test_vast_live.py +0 -0
  381. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_accounting_coverage.py +0 -0
  382. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_adapter_shard_completeness.py +0 -0
  383. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_agent_flash_cli_contract.py +0 -0
  384. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_algorithms.py +0 -0
  385. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_allocator.py +0 -0
  386. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_backend_common.py +0 -0
  387. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_backend_jobspec_contract.py +0 -0
  388. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_bake_kernel_cache.py +0 -0
  389. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_base_model_provenance.py +0 -0
  390. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_billing_retry.py +0 -0
  391. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_build_context_contract.py +0 -0
  392. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_cancel_remote.py +0 -0
  393. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_catalog_consistency.py +0 -0
  394. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_catalog_only_models.py +0 -0
  395. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_charge_pricing.py +0 -0
  396. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_checkpoint_lifecycle.py +0 -0
  397. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_checkpoints.py +0 -0
  398. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_cli_commands.py +0 -0
  399. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_cli_commands_coverage.py +0 -0
  400. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_cli_credential_shadowing.py +0 -0
  401. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_cli_errors.py +0 -0
  402. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_cli_estimate.py +0 -0
  403. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_cli_gpus_flag.py +0 -0
  404. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_cli_help.py +0 -0
  405. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_cli_main_coverage.py +0 -0
  406. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_cli_managed.py +0 -0
  407. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_cli_render_coverage.py +0 -0
  408. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_cli_render_theme.py +0 -0
  409. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_cli_traces.py +0 -0
  410. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_cli_wandb_warning.py +0 -0
  411. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_client.py +0 -0
  412. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_client_import_purity.py +0 -0
  413. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_client_server_integration.py +0 -0
  414. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_client_stream_reads.py +0 -0
  415. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_config_env_vars.py +0 -0
  416. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_config_overrides.py +0 -0
  417. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_console_upload.py +0 -0
  418. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_controlled_experiment_repairs.py +0 -0
  419. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_cost_analytical.py +0 -0
  420. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_cost_equation.py +0 -0
  421. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_cost_estimate.py +0 -0
  422. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_cost_hardware.py +0 -0
  423. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_cost_models.py +0 -0
  424. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_dataset_profile.py +0 -0
  425. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_deploy_alias_move_warning.py +0 -0
  426. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_deploy_latency.py +0 -0
  427. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_dev_channel.py +0 -0
  428. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_disk_gb.py +0 -0
  429. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_endpoint_name.py +0 -0
  430. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_env_cache_evict.py +0 -0
  431. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_env_delete.py +0 -0
  432. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_env_download.py +0 -0
  433. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_env_download_api.py +0 -0
  434. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_env_evaluations.py +0 -0
  435. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_env_list_api.py +0 -0
  436. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_env_list_cli.py +0 -0
  437. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_env_list_hub.py +0 -0
  438. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_env_no_install.py +0 -0
  439. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_env_publish.py +0 -0
  440. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_env_pull.py +0 -0
  441. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_env_pull_coverage.py +0 -0
  442. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_env_pull_loader_coverage.py +0 -0
  443. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_env_pull_managed_control_plane.py +0 -0
  444. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_env_push.py +0 -0
  445. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_env_rate_limit_resolve.py +0 -0
  446. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_env_ref_pinning.py +0 -0
  447. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_env_test.py +0 -0
  448. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_envs_coverage.py +0 -0
  449. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_export.py +0 -0
  450. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_flash_mvp.py +0 -0
  451. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_flash_worker.py +0 -0
  452. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_flashinfer_cache_dirs.py +0 -0
  453. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_freesolo_api_transport.py +0 -0
  454. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_fused_expert_warmstart.py +0 -0
  455. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_github_urlopen_retry.py +0 -0
  456. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_gpu_type_single_field.py +0 -0
  457. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_gpus.py +0 -0
  458. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_grpo_params.py +0 -0
  459. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_grpo_resident_sizing.py +0 -0
  460. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_grpo_reward_batching.py +0 -0
  461. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_health_liveness.py +0 -0
  462. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_hf_retry.py +0 -0
  463. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_idle_endpoint_reaper.py +0 -0
  464. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_infisical_secrets.py +0 -0
  465. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_instance_bootstrap_coverage.py +0 -0
  466. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_internal_client.py +0 -0
  467. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_kernel_cache.py +0 -0
  468. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_kernel_fingerprint.py +0 -0
  469. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_kv_util.py +0 -0
  470. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_lambda_api_coverage.py +0 -0
  471. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_lambda_runner.py +0 -0
  472. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_logging.py +0 -0
  473. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_login_perms.py +0 -0
  474. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_lora_rank_coverage.py +0 -0
  475. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_lora_rank_preflight.py +0 -0
  476. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_managed_config_fields.py +0 -0
  477. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_managed_hf_repo.py +0 -0
  478. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_metrics_schema_agent_contract.py +0 -0
  479. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_mig_guard.py +0 -0
  480. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_multi_gpu_gate.py +0 -0
  481. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_multimodal_training.py +0 -0
  482. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_named_reward_metrics.py +0 -0
  483. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_oom_escalate_gpu.py +0 -0
  484. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_opd.py +0 -0
  485. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_opd_limits.py +0 -0
  486. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_opd_multiturn_eos_boundary.py +0 -0
  487. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_opd_multiturn_failure_exit.py +0 -0
  488. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_opd_replay_guard.py +0 -0
  489. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_opd_resume_safety.py +0 -0
  490. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_opd_train.py +0 -0
  491. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_orchestrator_flash.py +0 -0
  492. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_packing.py +0 -0
  493. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_packing_coverage.py +0 -0
  494. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_parasail_teacher.py +0 -0
  495. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_poll_helpers.py +0 -0
  496. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_preflight.py +0 -0
  497. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_projects.py +0 -0
  498. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_prompt_budget.py +0 -0
  499. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_provider_preflight_coverage.py +0 -0
  500. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_provider_routing.py +0 -0
  501. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_provider_teardown_robustness.py +0 -0
  502. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_providers_symmetry.py +0 -0
  503. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_realized_cost.py +0 -0
  504. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_repo_cleanup.py +0 -0
  505. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_resolve_params_b.py +0 -0
  506. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_resume_on_retry.py +0 -0
  507. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_rl_train.py +0 -0
  508. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_rollout_samples.py +0 -0
  509. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_runmgmt.py +0 -0
  510. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_runpod_api_delete.py +0 -0
  511. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_runpod_key_fingerprint.py +0 -0
  512. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_runpod_key_waterfall.py +0 -0
  513. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_runtime_capsule.py +0 -0
  514. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_serve.py +0 -0
  515. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_serve_reasoning_content.py +0 -0
  516. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_server_api.py +0 -0
  517. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_server_app_coverage.py +0 -0
  518. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_server_auth_singleflight.py +0 -0
  519. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_server_billing.py +0 -0
  520. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_server_checkpoints_coverage.py +0 -0
  521. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_server_db.py +0 -0
  522. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_server_envs_coverage.py +0 -0
  523. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_server_locks_coverage.py +0 -0
  524. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_server_standalone.py +0 -0
  525. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_serving_context_preflight.py +0 -0
  526. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_serving_contract.py +0 -0
  527. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_serving_schema_coverage.py +0 -0
  528. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_sft_chunked_nll.py +0 -0
  529. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_sft_example_selection.py +0 -0
  530. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_sft_gc_off.py +0 -0
  531. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_sft_max_context.py +0 -0
  532. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_sft_startup_block.py +0 -0
  533. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_sft_train.py +0 -0
  534. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_sft_workload.py +0 -0
  535. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_spec_and_validation.py +0 -0
  536. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_spec_contract_bytes.py +0 -0
  537. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_step_floor.py +0 -0
  538. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_step_metrics.py +0 -0
  539. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_step_timing.py +0 -0
  540. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_structured_outputs.py +0 -0
  541. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_teacher_broker.py +0 -0
  542. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_teacher_encoding_contract.py +0 -0
  543. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_terminal_artifacts.py +0 -0
  544. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_thinking_config.py +0 -0
  545. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_train_context_preflight.py +0 -0
  546. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_training_controls.py +0 -0
  547. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_type_comment_prose.py +0 -0
  548. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_vast_api.py +0 -0
  549. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_vast_api_coverage.py +0 -0
  550. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_vast_offers.py +0 -0
  551. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_vast_provider_coverage.py +0 -0
  552. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_vast_runner.py +0 -0
  553. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_verified_revisions.py +0 -0
  554. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_verifiers.py +0 -0
  555. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_verl_checkpoint_export.py +0 -0
  556. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_verl_child_plugins.py +0 -0
  557. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_verl_silence_watchdog.py +0 -0
  558. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_version.py +0 -0
  559. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_vl_warmstart_adapter_keys.py +0 -0
  560. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_vram_architecture.py +0 -0
  561. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_wandb_link.py +0 -0
  562. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_wandb_naming.py +0 -0
  563. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_warmstart_adapter_download.py +0 -0
  564. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_warmstart_cross_repo.py +0 -0
  565. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_warmstart_error_attribution.py +0 -0
  566. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_weight_cache.py +0 -0
  567. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_worker_dryrun.py +0 -0
  568. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_worker_hardexit.py +0 -0
  569. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_worker_image.py +0 -0
  570. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_worker_init_heartbeat.py +0 -0
  571. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_worker_stack.py +0 -0
  572. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_worker_thinking.py +0 -0
  573. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_workflow_contracts.py +0 -0
  574. {freesolo_flash_dev-1.2.58 → freesolo_flash_dev-1.2.59}/tests/test_workload_profile.py +0 -0
  575. {freesolo_flash_dev-1.2.58 → 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.58
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
@@ -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
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "freesolo-flash-dev"
3
- version = "1.2.58"
3
+ version = "1.2.59"
4
4
  description ="Flash — managed LoRA post-training (SFT/GRPO/OPD) for Freesolo environments, driven by the `flash` CLI"
5
5
  readme = "README.md"
6
6
  # RunPod Flash supports Python 3.11-3.12 (not 3.13 yet).
@@ -137,7 +137,7 @@ artifacts = ["flash/py.typed"]
137
137
  # auto-published by .github/workflows/publish-dev.yml: a push to `dev` whose version isn't yet on
138
138
  # PyPI publishes it; pushes that don't change it find it already published and no-op. So cutting a
139
139
  # dev-channel release = bump this (and [project].version) and merge to `dev`.
140
- version = "1.2.58"
140
+ version = "1.2.59"
141
141
 
142
142
  [tool.pytest.ini_options]
143
143
  pythonpath = ["."]
@@ -7,6 +7,7 @@ import io
7
7
  import re
8
8
  import sys
9
9
  import tempfile
10
+ import time
10
11
  from types import SimpleNamespace
11
12
 
12
13
  import pytest
@@ -16,6 +17,17 @@ from tests._helpers.runner import provisioned_status
16
17
  _RUNPOD_FINGERPRINT = "rpk-0123456789ab"
17
18
 
18
19
 
20
+ def _live_clock_handle(jobs):
21
+ """A handle for a test that runs on the REAL clock rather than a faked one.
22
+
23
+ The poll loop measures its stall window from the persisted launch, so the fixed 1.0 default
24
+ below describes a job launched in 1970: fine for a test that also fakes `jobs.time.time` onto a
25
+ synthetic timeline, instantly "wedged" for one that does not. Tests asserting on the status
26
+ machine rather than on timing use this so their launch sits on the same clock they run against.
27
+ """
28
+ return _runpod_handle(jobs, started_ts=time.time())
29
+
30
+
19
31
  def _runpod_handle(
20
32
  jobs, endpoint_id="ep", endpoint_name="name", job_id="job", attempt=0, started_ts=1.0
21
33
  ):
@@ -184,7 +196,7 @@ def _poll(monkeypatch, statuses, heartbeats=None, stall_after_s=10.0):
184
196
  hb_iter = iter(heartbeats) if heartbeats is not None else None
185
197
 
186
198
  reader = (lambda force=False: next(hb_iter, None)) if hb_iter is not None else None
187
- h = _runpod_handle(jobs)
199
+ h = _live_clock_handle(jobs)
188
200
  ok_payload = {"acc": 1.0}
189
201
  return jobs.poll_job(
190
202
  h,
@@ -235,7 +247,7 @@ def test_poll_job_surfaces_heartbeat_before_terminal_return(monkeypatch):
235
247
  return heartbeat
236
248
 
237
249
  res = jobs.poll_job(
238
- _runpod_handle(jobs),
250
+ _live_clock_handle(jobs),
239
251
  interval_s=0,
240
252
  heartbeat_reader=read_heartbeat,
241
253
  )
@@ -314,7 +326,7 @@ def test_poll_job_failure_detail_redacts_secrets_in_provider_error_and_stdout(mo
314
326
  monkeypatch.setattr(jobs.time, "sleep", lambda s: None)
315
327
 
316
328
  res = jobs.poll_job(
317
- _runpod_handle(jobs),
329
+ _live_clock_handle(jobs),
318
330
  interval_s=0,
319
331
  heartbeat_reader=lambda force=False: None,
320
332
  )
@@ -345,7 +357,7 @@ def test_poll_job_failure_surfaces_forced_heartbeat(monkeypatch):
345
357
  }
346
358
 
347
359
  res = jobs.poll_job(
348
- _runpod_handle(jobs),
360
+ _live_clock_handle(jobs),
349
361
  interval_s=0,
350
362
  heartbeat_reader=lambda force=False: hb,
351
363
  log=log,
@@ -383,7 +395,7 @@ def test_poll_job_failure_appends_worker_artifacts(monkeypatch):
383
395
  )
384
396
 
385
397
  res = jobs.poll_job(
386
- _runpod_handle(jobs),
398
+ _live_clock_handle(jobs),
387
399
  interval_s=0,
388
400
  heartbeat_reader=lambda force=False: None,
389
401
  failure_detail_reader=failure_detail_reader,
@@ -423,7 +435,7 @@ def test_poll_job_platform_preempt_does_not_read_worker_artifacts(monkeypatch):
423
435
  raise AssertionError("platform terminations should not read worker artifacts")
424
436
 
425
437
  res = jobs.poll_job(
426
- _runpod_handle(jobs),
438
+ _live_clock_handle(jobs),
427
439
  interval_s=0,
428
440
  heartbeat_reader=lambda force=False: None,
429
441
  failure_detail_reader=failure_detail_reader,
@@ -437,12 +449,17 @@ def _poll_failed_with_heartbeat(monkeypatch, hb):
437
449
  from flash.providers.runpod import api as runpod_api
438
450
  from flash.providers.runpod import jobs
439
451
 
440
- hb = {"ts": 2.0, "attempt": 0, **hb}
452
+ # The heartbeat has to sit on the same timeline as the launch: `worker_flagged_retriable` only
453
+ # honours a heartbeat stamped at or after the launch it claims to describe, so a fixed ts=2.0
454
+ # against a real-clock launch is a 1970 artifact that is correctly ignored, and the retriable
455
+ # flag under test would never be read at all.
456
+ launch_ts = time.time()
457
+ hb = {"ts": launch_ts + 1.0, "attempt": 0, **hb}
441
458
  seq = iter([{"status": "IN_PROGRESS"}, {"status": "FAILED", "error": "boom"}])
442
459
  monkeypatch.setattr(runpod_api, "job_status", lambda eid, jid, **_kw: next(seq))
443
460
  monkeypatch.setattr(jobs.time, "sleep", lambda s: None)
444
461
  return jobs.poll_job(
445
- _runpod_handle(jobs),
462
+ _runpod_handle(jobs, started_ts=launch_ts),
446
463
  interval_s=0,
447
464
  heartbeat_reader=lambda force=False: hb,
448
465
  stall_after_s=10.0,
@@ -500,10 +517,17 @@ def test_poll_job_completed_decode_error_consults_worker_flags(monkeypatch):
500
517
  monkeypatch.setattr(
501
518
  runpod_api, "job_status", lambda eid, jid, **_kw: {"status": "COMPLETED", "output": bad}
502
519
  )
520
+ # the heartbeat shares the launch's timeline: a retriable flag stamped before launch is stale
521
+ # evidence and is correctly ignored, which would make this assert on the wrong reason.
522
+ launch_ts = time.time()
503
523
  res = jobs.poll_job(
504
- _runpod_handle(jobs),
524
+ _runpod_handle(jobs, started_ts=launch_ts),
505
525
  interval_s=0,
506
- heartbeat_reader=lambda force=False: {"retriable": True, "attempt": 0, "ts": 2.0},
526
+ heartbeat_reader=lambda force=False: {
527
+ "retriable": True,
528
+ "attempt": 0,
529
+ "ts": launch_ts + 1.0,
530
+ },
507
531
  failure_detail_reader=lambda force=False: "--- error_sft.txt ---\nCUDA out of memory",
508
532
  )
509
533
  assert res.failure == "job_preempted"
@@ -1861,7 +1885,7 @@ def test_poll_job_in_queue_then_progress_does_not_false_stall(monkeypatch):
1861
1885
  "endpoint_health_for_fingerprint",
1862
1886
  lambda eid, _fingerprint, **_kw: {"workers": {"ready": 1, "running": 1}},
1863
1887
  )
1864
- h = _runpod_handle(jobs)
1888
+ h = _live_clock_handle(jobs)
1865
1889
  res = jobs.poll_job(h, interval_s=0, heartbeat_reader=lambda: None, queue_grace_s=900.0)
1866
1890
  assert res.ok
1867
1891
 
@@ -2219,6 +2243,176 @@ def test_poll_job_stale_late_heartbeat_does_not_reset_progress(monkeypatch):
2219
2243
  assert fresh_run > none_run, "a genuinely newer heartbeat does reset progress (stalls later)"
2220
2244
 
2221
2245
 
2246
+ @pytest.mark.parametrize(
2247
+ ("last_hb_attempt", "last_hb_ts"),
2248
+ [(-1, 0.0), (0, 50.0)],
2249
+ ids=["first-current-attempt-heartbeat", "later-current-attempt-heartbeat"],
2250
+ )
2251
+ def test_older_heartbeat_cannot_regress_status_progress_anchor(
2252
+ monkeypatch, last_hb_attempt, last_hb_ts
2253
+ ):
2254
+ # a queue exemption or status transition can advance the shared progress anchor beyond the
2255
+ # worker timestamp. a heartbeat that becomes visible later may still advance heartbeat-specific
2256
+ # bookkeeping, but neither credit branch may move the stall anchor backward.
2257
+ from flash.providers.runpod import jobs
2258
+
2259
+ job_execution = sys.modules["flash.providers.runpod.job_execution"]
2260
+ heartbeat_key = ("boot", None, 100.0, 0)
2261
+ monkeypatch.setattr(
2262
+ job_execution,
2263
+ "surface_heartbeat",
2264
+ lambda _reader, _last_key, _say: (heartbeat_key, "boot"),
2265
+ )
2266
+ monkeypatch.setattr(jobs.time, "time", lambda: 600.0)
2267
+ context = SimpleNamespace(
2268
+ heartbeat_reader=lambda: None,
2269
+ say=lambda _message: None,
2270
+ current_attempt=0,
2271
+ launch_ts=1.0,
2272
+ )
2273
+ state = SimpleNamespace(
2274
+ last_hb_key=None,
2275
+ last_hb_ts=last_hb_ts,
2276
+ last_hb_attempt=last_hb_attempt,
2277
+ last_progress=500.0,
2278
+ seen_training_hb=False,
2279
+ ever_saw_worker=True,
2280
+ )
2281
+
2282
+ job_execution._update_heartbeat(context, state)
2283
+
2284
+ assert state.last_progress == 500.0
2285
+
2286
+
2287
+ def _stall_clock_at_giveup(
2288
+ monkeypatch, *, started_ts, heartbeats=(), step_s=100.0, clock_at=5000.0
2289
+ ):
2290
+ """Poll an ALREADY-PLACED job and return the absolute fake-clock time it gave up at.
2291
+
2292
+ IN_PROGRESS from the first read, so the queued-capacity exemption never applies and the value
2293
+ seeded into ``last_progress`` is the only thing anchoring the stall window. ``clock_at`` is where
2294
+ this poll's wall clock starts; a ``started_ts`` well below it is a launch in the past, i.e. a
2295
+ delayed reattach. The handle rejects a non-positive launch, so the clock starts high rather than
2296
+ the launch going negative.
2297
+ """
2298
+ from flash.providers.runpod import api as runpod_api
2299
+ from flash.providers.runpod import jobs
2300
+
2301
+ monkeypatch.setattr(runpod_api, "job_status", lambda eid, jid, **_kw: {"status": "IN_PROGRESS"})
2302
+ monkeypatch.setattr(jobs.time, "sleep", lambda s: None)
2303
+ state = {"t": clock_at}
2304
+
2305
+ def _time():
2306
+ state["t"] += step_s
2307
+ return state["t"]
2308
+
2309
+ monkeypatch.setattr(jobs.time, "time", _time)
2310
+ hbs = iter(list(heartbeats))
2311
+ res = jobs.poll_job(
2312
+ _runpod_handle(jobs, started_ts=started_ts),
2313
+ interval_s=0,
2314
+ heartbeat_reader=lambda: next(hbs, None),
2315
+ stall_after_s=150.0,
2316
+ setup_grace_s=600.0,
2317
+ )
2318
+ assert res.failure == "stalled", res
2319
+ return state["t"]
2320
+
2321
+
2322
+ def test_a_reattached_wedged_worker_is_measured_from_launch_not_from_this_polls_start(monkeypatch):
2323
+ # A reattach has been BILLING since launch, so the stall window has to be measured from the
2324
+ # persisted launch timestamp. Seeding it from `time.time()` at poll start meant every reattach
2325
+ # handed a worker that was already wedged a complete fresh setup window, and a supervisor that
2326
+ # reattaches repeatedly could keep a dead worker on a paid GPU until the run's wall deadline.
2327
+ #
2328
+ # The job is IN_PROGRESS from the first read, so the queued-capacity exemption -- which re-anchors
2329
+ # `last_progress` on every pre-grant poll, and is what made the wrong seed survivable for a job
2330
+ # queued from the start -- never fires here. This is the placed-at-attach case where the seed is
2331
+ # the only anchor.
2332
+ #
2333
+ # Assert on the absolute clock at give-up, not on the "no worker progress for Ns" figure in the
2334
+ # detail: that figure is derived from `last_progress` and reads ~the same either way, so it
2335
+ # cannot tell the fixed and broken code apart.
2336
+ # attached at launch: the setup grace has not been spent, so the full window remains.
2337
+ at_launch = _stall_clock_at_giveup(monkeypatch, started_ts=5000.0)
2338
+ # same wedge, but launched 5000s before this poll attached: that grace is already gone.
2339
+ long_after_launch = _stall_clock_at_giveup(monkeypatch, started_ts=1.0)
2340
+ assert long_after_launch < at_launch, (
2341
+ f"a worker wedged since a launch 5000s ago was torn down at {long_after_launch}s, no sooner "
2342
+ f"than one attached at launch ({at_launch}s); the stall clock anchors on poll start, not launch"
2343
+ )
2344
+
2345
+
2346
+ def test_a_heartbeat_written_before_the_reattach_buys_no_fresh_stall_window(monkeypatch):
2347
+ # Crediting progress at READ time means a heartbeat written long ago and surfaced now pays out a
2348
+ # full fresh window, so a worker that stopped producing heartbeats before we attached looks alive
2349
+ # for one more grace period. Credit the heartbeat's OWN ts (clamped to [launch, now]) instead:
2350
+ # it describes when the worker made progress, not when we got around to looking.
2351
+ #
2352
+ # Both runs see exactly ONE staged heartbeat, so the only difference is its timestamp.
2353
+ stale = _stall_clock_at_giveup(
2354
+ monkeypatch,
2355
+ started_ts=5000.0,
2356
+ heartbeats=[{"stage": "train", "step": 1, "ts": 5001.0, "attempt": 0}],
2357
+ )
2358
+ current = _stall_clock_at_giveup(
2359
+ monkeypatch,
2360
+ started_ts=5000.0,
2361
+ heartbeats=[{"stage": "train", "step": 1, "ts": 5400.0, "attempt": 0}],
2362
+ )
2363
+ assert stale < current, (
2364
+ f"a heartbeat stamped at launch (ts=5001.0) held the run to {stale}s, as long as one stamped "
2365
+ f"at ts=5400.0 ({current}s); progress is credited at read time, not at the heartbeat's own ts"
2366
+ )
2367
+
2368
+
2369
+ def test_a_heartbeat_from_a_prior_attempt_buys_this_attempt_no_progress(monkeypatch):
2370
+ # A retry reuses the same heartbeat path, so a leftover heartbeat from attempt 0 is still
2371
+ # readable while attempt 1 is running. Crediting it would let the PREVIOUS attempt's work stand
2372
+ # as proof that THIS one is progressing. The attempt identity has to gate the credit, not just
2373
+ # the OOM flags.
2374
+ #
2375
+ # Both runs are attempt 1 and see exactly one heartbeat; only its `attempt` field differs. The
2376
+ # own-attempt run gives up SOONER, which is the tell: its heartbeat is a training heartbeat, so
2377
+ # it both moves the clock and tightens the window from setup grace to the stall limit. The
2378
+ # prior-attempt heartbeat must do neither, leaving the wider setup window running from launch.
2379
+ # Asserting "stale lasts longer" therefore proves the heartbeat was ignored end to end; the
2380
+ # reverse ordering would mean prior-attempt evidence had been credited.
2381
+ from flash.providers.runpod import api as runpod_api
2382
+ from flash.providers.runpod import jobs
2383
+
2384
+ def _giveup_with(hb_attempt):
2385
+ monkeypatch.setattr(
2386
+ runpod_api, "job_status", lambda eid, jid, **_kw: {"status": "IN_PROGRESS"}
2387
+ )
2388
+ monkeypatch.setattr(jobs.time, "sleep", lambda s: None)
2389
+ state = {"t": 5000.0}
2390
+
2391
+ def _time():
2392
+ state["t"] += 100.0
2393
+ return state["t"]
2394
+
2395
+ monkeypatch.setattr(jobs.time, "time", _time)
2396
+ hbs = iter([{"stage": "train", "step": 1, "ts": 5400.0, "attempt": hb_attempt}])
2397
+ res = jobs.poll_job(
2398
+ _runpod_handle(jobs, attempt=1, started_ts=5000.0),
2399
+ interval_s=0,
2400
+ heartbeat_reader=lambda: next(hbs, None),
2401
+ stall_after_s=150.0,
2402
+ setup_grace_s=600.0,
2403
+ current_attempt=1,
2404
+ )
2405
+ assert res.failure == "stalled", res
2406
+ return state["t"]
2407
+
2408
+ stale_attempt = _giveup_with(0)
2409
+ this_attempt = _giveup_with(1)
2410
+ assert stale_attempt > this_attempt, (
2411
+ f"attempt 1 given only a stale attempt=0 heartbeat behaved identically to one given its "
2412
+ f"own ({stale_attempt}s vs {this_attempt}s); prior-attempt evidence is being credited"
2413
+ )
2414
+
2415
+
2222
2416
  def test_poll_job_gapfill_step0_does_not_tighten(monkeypatch):
2223
2417
  # The train-liveness gap-filler emits rl_step/sft_step at step=0 throughout the silent FIRST step
2224
2418
  # (a cold vLLM rollout can run many minutes before global_step ticks to 1). That step=0 ping is a
@@ -6650,7 +6844,7 @@ def test_runpod_completed_metrics_probes_after_expired_recovery_grace(monkeypatc
6650
6844
 
6651
6845
  monkeypatch.setattr(runpod_api, "job_status", completed_status)
6652
6846
  metrics = lifecycle._runpod_completed_metrics(
6653
- _runpod_handle(jobs),
6847
+ _live_clock_handle(jobs),
6654
6848
  deadline_at=now - lifecycle._RECOVERY_MARKER_GRACE_S - 1.0,
6655
6849
  )
6656
6850
 
@@ -6678,7 +6872,7 @@ def test_runpod_completed_metrics_caps_probe_deadline_when_wall_deadline_far_fut
6678
6872
 
6679
6873
  monkeypatch.setattr(runpod_api, "job_status", completed_status)
6680
6874
  metrics = lifecycle._runpod_completed_metrics(
6681
- _runpod_handle(jobs),
6875
+ _live_clock_handle(jobs),
6682
6876
  deadline_at=now + 7_200.0, # wall deadline hours in the future
6683
6877
  )
6684
6878
 
@@ -1052,7 +1052,7 @@ wheels = [
1052
1052
 
1053
1053
  [[package]]
1054
1054
  name = "freesolo-flash"
1055
- version = "1.2.58"
1055
+ version = "1.2.59"
1056
1056
  source = { editable = "." }
1057
1057
 
1058
1058
  [package.optional-dependencies]