freesolo-flash-dev 1.2.64__tar.gz → 1.2.66__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 (587) hide show
  1. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/PKG-INFO +1 -1
  2. freesolo_flash_dev-1.2.66/flash/_internal/diagnostics.py +170 -0
  3. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/__init__.py +11 -17
  4. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/perf/__init__.py +2 -2
  5. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/perf/lifecycle.py +48 -85
  6. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/_lifecycle/bootstrap_secrets.py +83 -18
  7. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/runpod/serverless/endpoints.py +96 -34
  8. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/runner/supervise/seed_submission.py +21 -15
  9. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/server/domain/projects.py +34 -55
  10. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/pyproject.toml +2 -2
  11. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_backend_common.py +81 -0
  12. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_flash_worker.py +176 -1
  13. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_instance_bootstrap_coverage.py +59 -0
  14. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_oom_escalate_gpu.py +125 -32
  15. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_opd_resume_safety.py +96 -21
  16. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_projects.py +232 -49
  17. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_server_api.py +62 -0
  18. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/uv.lock +1 -1
  19. freesolo_flash_dev-1.2.64/flash/_internal/diagnostics.py +0 -106
  20. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/.dockerignore +0 -0
  21. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/.env.example +0 -0
  22. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/.github/CODEOWNERS +0 -0
  23. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  24. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  25. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  26. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  27. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/.github/dependabot.yml +0 -0
  28. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/.github/workflows/auto-rebake.yml +0 -0
  29. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/.github/workflows/bake-kernel-cache.yml +0 -0
  30. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/.github/workflows/ci.yml +0 -0
  31. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/.github/workflows/main-source-guard.yml +0 -0
  32. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/.github/workflows/notify-tests-repo.yml +0 -0
  33. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/.github/workflows/publish-dev.yml +0 -0
  34. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/.github/workflows/publish-image.yml +0 -0
  35. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/.github/workflows/publish.yml +0 -0
  36. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/.github/workflows/version-parity.yml +0 -0
  37. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/.github/workflows/worker-image.yml +0 -0
  38. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/.gitignore +0 -0
  39. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/CHANGELOG.md +0 -0
  40. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/CODE_OF_CONDUCT.md +0 -0
  41. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/CONTRIBUTING.md +0 -0
  42. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/Dockerfile +0 -0
  43. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/Dockerfile.worker +0 -0
  44. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/LICENSE +0 -0
  45. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/NOTICE +0 -0
  46. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/README.md +0 -0
  47. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/SECURITY.md +0 -0
  48. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/SELF_HOSTING.md +0 -0
  49. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/build/kernel_cache/.gitignore +0 -0
  50. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/build/kernel_cache/.keep +0 -0
  51. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/deploy/infisical/README.md +0 -0
  52. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/deploy/infisical/entrypoint.sh +0 -0
  53. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/docker/Dockerfile.kernelcache +0 -0
  54. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/docker/Dockerfile.kernelcache.relayer +0 -0
  55. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/docker/bake_kernel_cache.py +0 -0
  56. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/docker/bake_pod_entry.py +0 -0
  57. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/docker/extract_cudart_fix.py +0 -0
  58. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/docker/kernel_fingerprint.py +0 -0
  59. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/docker/make_rp_handler.py +0 -0
  60. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/__init__.py +0 -0
  61. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/_internal/__init__.py +0 -0
  62. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/_internal/channel.py +0 -0
  63. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/_internal/fileio.py +0 -0
  64. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/_internal/logging.py +0 -0
  65. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/_internal/paths.py +0 -0
  66. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/adapters/__init__.py +0 -0
  67. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/adapters/artifacts.py +0 -0
  68. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/adapters/fused_experts.py +0 -0
  69. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/adapters/lora_rank.py +0 -0
  70. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/cli/__init__.py +0 -0
  71. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/cli/__main__.py +0 -0
  72. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/cli/commands/__init__.py +0 -0
  73. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/cli/commands/deploy.py +0 -0
  74. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/cli/commands/env/__init__.py +0 -0
  75. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/cli/commands/env/episode.py +0 -0
  76. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/cli/commands/env/eval.py +0 -0
  77. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/cli/commands/env/eval_args.py +0 -0
  78. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/cli/commands/env/imports.py +0 -0
  79. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/cli/commands/env/list.py +0 -0
  80. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/cli/commands/env/push.py +0 -0
  81. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/cli/commands/env/retained.py +0 -0
  82. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/cli/commands/env/setup.py +0 -0
  83. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/cli/commands/env/setup_wandb.py +0 -0
  84. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/cli/commands/env/test.py +0 -0
  85. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/cli/commands/env/test_evaluations.py +0 -0
  86. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/cli/commands/env/test_params.py +0 -0
  87. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/cli/commands/env/test_warnings.py +0 -0
  88. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/cli/commands/prompt_budget.py +0 -0
  89. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/cli/commands/traces.py +0 -0
  90. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/cli/commands/train_cost.py +0 -0
  91. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/cli/scaffold/TRAINING.md +0 -0
  92. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/cli/scaffold/__init__.py +0 -0
  93. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/cli/ui/__init__.py +0 -0
  94. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/cli/ui/cost.py +0 -0
  95. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/cli/ui/env_panels.py +0 -0
  96. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/cli/ui/heartbeat.py +0 -0
  97. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/cli/ui/render.py +0 -0
  98. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/cli/ui/tables.py +0 -0
  99. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/cli/ui/tty.py +0 -0
  100. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/client/__init__.py +0 -0
  101. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/client/config.py +0 -0
  102. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/client/freesolo_api.py +0 -0
  103. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/client/http.py +0 -0
  104. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/client/runtime_secrets.py +0 -0
  105. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/client/shapes.py +0 -0
  106. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/client/specs.py +0 -0
  107. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/client/streaming.py +0 -0
  108. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/content/__init__.py +0 -0
  109. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/content/multimodal.py +0 -0
  110. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/content/structured_outputs.py +0 -0
  111. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/content/thinking.py +0 -0
  112. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/core/__init__.py +0 -0
  113. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/core/catalog.py +0 -0
  114. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/core/spec.py +0 -0
  115. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/core/spec_persistence.py +0 -0
  116. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/cost/__init__.py +0 -0
  117. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/cost/analytical.py +0 -0
  118. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/cost/facts.py +0 -0
  119. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/cost/spec.py +0 -0
  120. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/cost/types.py +0 -0
  121. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/__init__.py +0 -0
  122. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/huggingface.py +0 -0
  123. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/plan/__init__.py +0 -0
  124. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/plan/kv_sizing.py +0 -0
  125. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/plan/model_config_probe.py +0 -0
  126. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/plan/prompt_budget.py +0 -0
  127. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/plan/recipe.py +0 -0
  128. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/plan/steps.py +0 -0
  129. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/plan/vram.py +0 -0
  130. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/profiling/__init__.py +0 -0
  131. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/profiling/dataset_profile.py +0 -0
  132. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/profiling/image_tokens.py +0 -0
  133. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/profiling/reasoning_render.py +0 -0
  134. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/profiling/sft_image_rows.py +0 -0
  135. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/profiling/sft_workload.py +0 -0
  136. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/profiling/tokenizer.py +0 -0
  137. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/profiling/workload_profile.py +0 -0
  138. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/result/__init__.py +0 -0
  139. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/result/accounting.py +0 -0
  140. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/result/rollout_samples.py +0 -0
  141. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/__main__.py +0 -0
  142. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/backend_common.py +0 -0
  143. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/entry/__init__.py +0 -0
  144. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/entry/opd.py +0 -0
  145. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/entry/rl.py +0 -0
  146. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/entry/sft.py +0 -0
  147. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/io/__init__.py +0 -0
  148. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/io/heartbeat.py +0 -0
  149. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/io/hf.py +0 -0
  150. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/io/prefetch.py +0 -0
  151. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/io/wandb_log.py +0 -0
  152. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/model/__init__.py +0 -0
  153. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/model/adapter.py +0 -0
  154. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/model/chatml_mask.py +0 -0
  155. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/model/decoding.py +0 -0
  156. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/model/lora.py +0 -0
  157. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/model/packing.py +0 -0
  158. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/opd_train.py +0 -0
  159. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/opd_train_runner.py +0 -0
  160. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/perf/diagnostics.py +0 -0
  161. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/perf/liger.py +0 -0
  162. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/perf/memory.py +0 -0
  163. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/rl_train.py +0 -0
  164. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/rl_train_runner.py +0 -0
  165. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/runtime/__init__.py +0 -0
  166. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/runtime/kernel_warmup.py +0 -0
  167. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/runtime/pkg_proxy.py +0 -0
  168. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/runtime/rng.py +0 -0
  169. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/score_batcher.py +0 -0
  170. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/sft_train.py +0 -0
  171. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/sft_train_runner.py +0 -0
  172. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/teacher/__init__.py +0 -0
  173. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/teacher/client.py +0 -0
  174. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/teacher/encoding.py +0 -0
  175. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/teacher/tokenizer_align.py +0 -0
  176. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/__init__.py +0 -0
  177. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/core/__init__.py +0 -0
  178. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/core/checkpoint_lifecycle.py +0 -0
  179. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/core/child/__init__.py +0 -0
  180. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/core/child/glue.py +0 -0
  181. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/core/child/runtime.py +0 -0
  182. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/core/step_timing.py +0 -0
  183. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/finalize.py +0 -0
  184. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/opd/__init__.py +0 -0
  185. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/opd/batching.py +0 -0
  186. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/opd/bridge.py +0 -0
  187. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/opd/bridge_failures.py +0 -0
  188. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/opd/child/__init__.py +0 -0
  189. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/opd/child/bridge.py +0 -0
  190. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/opd/child/entry.py +0 -0
  191. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/opd/child/multiturn.py +0 -0
  192. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/opd/child/plugin.py +0 -0
  193. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/opd/child/replay_guard.py +0 -0
  194. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/opd/child/runtime.py +0 -0
  195. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/opd/child/structured.py +0 -0
  196. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/opd/failures.py +0 -0
  197. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/opd/gkd.py +0 -0
  198. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/opd/multiturn_validation.py +0 -0
  199. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/opd/overrides.py +0 -0
  200. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/opd/prompts.py +0 -0
  201. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/opd/reporting.py +0 -0
  202. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/opd/scoring.py +0 -0
  203. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/opd/state.py +0 -0
  204. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/opd/validation.py +0 -0
  205. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/rl/__init__.py +0 -0
  206. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/rl/checkpoints.py +0 -0
  207. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/rl/child/__init__.py +0 -0
  208. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/rl/child/entry.py +0 -0
  209. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/rl/child/multiturn.py +0 -0
  210. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/rl/child/patches.py +0 -0
  211. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/rl/child/plugin.py +0 -0
  212. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/rl/config.py +0 -0
  213. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/rl/inputs.py +0 -0
  214. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/rl/multi_turn.py +0 -0
  215. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/rl/reward_module.py +0 -0
  216. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/rl/scoring.py +0 -0
  217. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/rl/single_turn.py +0 -0
  218. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/rl/verl_config.py +0 -0
  219. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/sft/__init__.py +0 -0
  220. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/sft/checkpoints.py +0 -0
  221. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/sft/child/entry.py +0 -0
  222. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/sft/child/plugin.py +0 -0
  223. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/train/sft/config.py +0 -0
  224. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/verl/__init__.py +0 -0
  225. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/verl/capabilities.py +0 -0
  226. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/verl/checkpoints.py +0 -0
  227. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/verl/child_io.py +0 -0
  228. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/verl/diagnostics.py +0 -0
  229. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/verl/parallelism.py +0 -0
  230. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker/verl/parent_work.py +0 -0
  231. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/engine/worker_entrypoint.py +0 -0
  232. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/envs/__init__.py +0 -0
  233. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/envs/adapter.py +0 -0
  234. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/envs/base.py +0 -0
  235. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/envs/cache_security.py +0 -0
  236. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/envs/dataset_selection.py +0 -0
  237. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/envs/evaluations.py +0 -0
  238. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/envs/identity.py +0 -0
  239. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/envs/loader.py +0 -0
  240. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/envs/namespace_listing.py +0 -0
  241. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/envs/package/__init__.py +0 -0
  242. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/envs/package/limits.py +0 -0
  243. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/envs/package/unpack.py +0 -0
  244. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/envs/pull.py +0 -0
  245. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/__init__.py +0 -0
  246. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/_lifecycle/__init__.py +0 -0
  247. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/_lifecycle/auth.py +0 -0
  248. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/_lifecycle/bootstrap.py +0 -0
  249. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/_lifecycle/bootstrap_console.py +0 -0
  250. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/_lifecycle/bootstrap_pip.py +0 -0
  251. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/_lifecycle/deadline.py +0 -0
  252. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/_lifecycle/host/__init__.py +0 -0
  253. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/_lifecycle/host/deadline_sleep.py +0 -0
  254. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/_lifecycle/host/failmark.py +0 -0
  255. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/_lifecycle/host/hostlog.py +0 -0
  256. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/_lifecycle/http.py +0 -0
  257. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/_lifecycle/instance.py +0 -0
  258. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/_lifecycle/poll.py +0 -0
  259. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/_lifecycle/poll_instance.py +0 -0
  260. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/_lifecycle/provider.py +0 -0
  261. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/_lifecycle/terminal_artifacts.py +0 -0
  262. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/_lifecycle/worker.py +0 -0
  263. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/allocator.py +0 -0
  264. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/artifacts/__init__.py +0 -0
  265. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/artifacts/hf.py +0 -0
  266. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/artifacts/preload_runpod.py +0 -0
  267. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/artifacts/weight_cache.py +0 -0
  268. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/base.py +0 -0
  269. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/fit_errors.py +0 -0
  270. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/lambda_/__init__.py +0 -0
  271. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/lambda_/api.py +0 -0
  272. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/lambda_/auth.py +0 -0
  273. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/lambda_/gpus.py +0 -0
  274. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/lambda_/jobs/__init__.py +0 -0
  275. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/lambda_/jobs/builders.py +0 -0
  276. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/lambda_/jobs/reap.py +0 -0
  277. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/lambda_/preflight.py +0 -0
  278. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/lambda_/pricing.py +0 -0
  279. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/preflight.py +0 -0
  280. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/realized.py +0 -0
  281. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/runpod/__init__.py +0 -0
  282. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/runpod/api.py +0 -0
  283. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/runpod/auth.py +0 -0
  284. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/runpod/cost.py +0 -0
  285. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/runpod/gpus.py +0 -0
  286. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/runpod/job_execution.py +0 -0
  287. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/runpod/jobs.py +0 -0
  288. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/runpod/preflight.py +0 -0
  289. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/runpod/pricing.py +0 -0
  290. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/runpod/resources.py +0 -0
  291. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/runpod/serverless/__init__.py +0 -0
  292. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/sharding.py +0 -0
  293. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/vast/__init__.py +0 -0
  294. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/vast/api.py +0 -0
  295. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/vast/auth.py +0 -0
  296. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/vast/jobs/__init__.py +0 -0
  297. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/vast/jobs/builders.py +0 -0
  298. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/vast/preflight.py +0 -0
  299. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/providers/vast/pricing.py +0 -0
  300. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/py.typed +0 -0
  301. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/runner/__init__.py +0 -0
  302. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/runner/artifacts.py +0 -0
  303. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/runner/attempts.py +0 -0
  304. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/runner/costs.py +0 -0
  305. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/runner/deadlines.py +0 -0
  306. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/runner/preparation.py +0 -0
  307. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/runner/reconciliation.py +0 -0
  308. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/runner/results/__init__.py +0 -0
  309. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/runner/results/checkpoints.py +0 -0
  310. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/runner/results/verified_revisions.py +0 -0
  311. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/runner/status.py +0 -0
  312. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/runner/submit.py +0 -0
  313. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/runner/supervise/__init__.py +0 -0
  314. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/runner/supervise/attach.py +0 -0
  315. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/runner/supervise/deploy.py +0 -0
  316. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/runner/supervise/lifecycle.py +0 -0
  317. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/runner/supervise/recovery.py +0 -0
  318. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/runner/supervise/retry_decision.py +0 -0
  319. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/runner/supervise/transitions.py +0 -0
  320. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/runner/weight_cache.py +0 -0
  321. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/runtime_capsule/__init__.py +0 -0
  322. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/runtime_capsule/build.py +0 -0
  323. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/runtime_capsule/manifest.py +0 -0
  324. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/runtime_capsule/profiles.py +0 -0
  325. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/schema/__init__.py +0 -0
  326. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/schema/fields.py +0 -0
  327. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/serve/__init__.py +0 -0
  328. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/serve/adapter_check.py +0 -0
  329. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/serve/deploy.py +0 -0
  330. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/serve/errors.py +0 -0
  331. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/serve/export.py +0 -0
  332. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/serve/preflight.py +0 -0
  333. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/serve/responses.py +0 -0
  334. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/serve/streaming.py +0 -0
  335. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/serve/thinking.py +0 -0
  336. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/serve/urls.py +0 -0
  337. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/server/__init__.py +0 -0
  338. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/server/__main__.py +0 -0
  339. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/server/app.py +0 -0
  340. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/server/billing/__init__.py +0 -0
  341. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/server/billing/charges.py +0 -0
  342. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/server/billing/retry.py +0 -0
  343. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/server/domain/__init__.py +0 -0
  344. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/server/domain/checkpoints.py +0 -0
  345. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/server/domain/environment_registry.py +0 -0
  346. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/server/domain/envs.py +0 -0
  347. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/server/domain/reconcile.py +0 -0
  348. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/server/domain/repo_cleanup.py +0 -0
  349. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/server/domain/run_registry.py +0 -0
  350. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/server/domain/teacher_broker.py +0 -0
  351. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/server/domain/teacher_errors.py +0 -0
  352. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/server/domain/teacher_requests.py +0 -0
  353. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/server/platform/__init__.py +0 -0
  354. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/server/platform/auth.py +0 -0
  355. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/server/platform/db.py +0 -0
  356. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/server/platform/deps.py +0 -0
  357. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/server/platform/internal_client.py +0 -0
  358. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/server/platform/locks.py +0 -0
  359. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/server/platform/runtime.py +0 -0
  360. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/server/routes/__init__.py +0 -0
  361. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/server/routes/envs.py +0 -0
  362. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/server/routes/meta.py +0 -0
  363. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/server/routes/runs.py +0 -0
  364. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/server/routes/serving.py +0 -0
  365. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/server/routes/serving_completion.py +0 -0
  366. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/server/routes/serving_revisions.py +0 -0
  367. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/server/routes/serving_smoke.py +0 -0
  368. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/server/routes/teacher.py +0 -0
  369. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/teacher/__init__.py +0 -0
  370. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/teacher/limits.py +0 -0
  371. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/flash/teacher/retry_contract.py +0 -0
  372. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/scripts/build_dev_dist.py +0 -0
  373. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/scripts/check_file_size.py +0 -0
  374. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/scripts/check_function_size.py +0 -0
  375. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/scripts/check_verl_pin_exists.py +0 -0
  376. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/scripts/scrub_history.sh +0 -0
  377. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/__init__.py +0 -0
  378. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/_helpers/__init__.py +0 -0
  379. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/_helpers/profile.py +0 -0
  380. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/_helpers/runner.py +0 -0
  381. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/_helpers/specs.py +0 -0
  382. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/_helpers/teacher.py +0 -0
  383. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/_helpers/vast.py +0 -0
  384. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/capture_image_sft_processor_oracle.py +0 -0
  385. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/conftest.py +0 -0
  386. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/fixtures/image_sft_processor_oracle.json +0 -0
  387. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/fixtures/math_eval.jsonl +0 -0
  388. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/fixtures/math_train.jsonl +0 -0
  389. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/live/__init__.py +0 -0
  390. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/live/conftest.py +0 -0
  391. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/live/test_lambda_live.py +0 -0
  392. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/live/test_runpod_live.py +0 -0
  393. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/live/test_sft_thinking_render_live.py +0 -0
  394. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/live/test_vast_live.py +0 -0
  395. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_accounting_coverage.py +0 -0
  396. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_adapter_shard_completeness.py +0 -0
  397. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_agent_flash_cli_contract.py +0 -0
  398. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_algorithms.py +0 -0
  399. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_allocator.py +0 -0
  400. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_backend_jobspec_contract.py +0 -0
  401. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_bake_kernel_cache.py +0 -0
  402. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_base_model_provenance.py +0 -0
  403. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_billing_retry.py +0 -0
  404. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_build_context_contract.py +0 -0
  405. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_cancel_remote.py +0 -0
  406. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_catalog_consistency.py +0 -0
  407. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_catalog_only_models.py +0 -0
  408. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_charge_pricing.py +0 -0
  409. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_checkpoint_lifecycle.py +0 -0
  410. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_checkpoints.py +0 -0
  411. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_cli_commands.py +0 -0
  412. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_cli_commands_coverage.py +0 -0
  413. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_cli_credential_shadowing.py +0 -0
  414. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_cli_errors.py +0 -0
  415. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_cli_estimate.py +0 -0
  416. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_cli_gpus_flag.py +0 -0
  417. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_cli_help.py +0 -0
  418. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_cli_main_coverage.py +0 -0
  419. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_cli_managed.py +0 -0
  420. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_cli_render_coverage.py +0 -0
  421. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_cli_render_theme.py +0 -0
  422. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_cli_traces.py +0 -0
  423. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_cli_wandb_warning.py +0 -0
  424. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_client.py +0 -0
  425. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_client_import_purity.py +0 -0
  426. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_client_server_integration.py +0 -0
  427. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_client_stream_reads.py +0 -0
  428. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_config_env_vars.py +0 -0
  429. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_config_overrides.py +0 -0
  430. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_console_upload.py +0 -0
  431. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_controlled_experiment_repairs.py +0 -0
  432. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_cost_analytical.py +0 -0
  433. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_cost_equation.py +0 -0
  434. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_cost_estimate.py +0 -0
  435. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_cost_hardware.py +0 -0
  436. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_cost_models.py +0 -0
  437. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_dataset_profile.py +0 -0
  438. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_deploy_alias_move_warning.py +0 -0
  439. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_deploy_latency.py +0 -0
  440. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_dev_channel.py +0 -0
  441. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_disk_gb.py +0 -0
  442. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_endpoint_name.py +0 -0
  443. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_env_cache_evict.py +0 -0
  444. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_env_delete.py +0 -0
  445. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_env_download.py +0 -0
  446. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_env_download_api.py +0 -0
  447. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_env_evaluations.py +0 -0
  448. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_env_list_api.py +0 -0
  449. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_env_list_cli.py +0 -0
  450. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_env_list_hub.py +0 -0
  451. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_env_no_install.py +0 -0
  452. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_env_publish.py +0 -0
  453. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_env_pull.py +0 -0
  454. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_env_pull_coverage.py +0 -0
  455. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_env_pull_loader_coverage.py +0 -0
  456. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_env_pull_managed_control_plane.py +0 -0
  457. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_env_push.py +0 -0
  458. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_env_rate_limit_resolve.py +0 -0
  459. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_env_ref_pinning.py +0 -0
  460. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_env_test.py +0 -0
  461. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_envs_coverage.py +0 -0
  462. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_export.py +0 -0
  463. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_flash_mvp.py +0 -0
  464. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_flashinfer_cache_dirs.py +0 -0
  465. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_freesolo_api_transport.py +0 -0
  466. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_fused_expert_warmstart.py +0 -0
  467. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_github_urlopen_retry.py +0 -0
  468. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_gpu_type_single_field.py +0 -0
  469. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_gpus.py +0 -0
  470. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_grpo_params.py +0 -0
  471. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_grpo_resident_sizing.py +0 -0
  472. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_grpo_reward_batching.py +0 -0
  473. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_health_liveness.py +0 -0
  474. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_hf_retry.py +0 -0
  475. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_idle_endpoint_reaper.py +0 -0
  476. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_image_sft_markers.py +0 -0
  477. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_image_sft_processor_parity.py +0 -0
  478. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_image_tokens.py +0 -0
  479. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_infisical_secrets.py +0 -0
  480. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_internal_client.py +0 -0
  481. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_jobs.py +0 -0
  482. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_kernel_cache.py +0 -0
  483. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_kernel_fingerprint.py +0 -0
  484. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_kv_util.py +0 -0
  485. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_lambda_api_coverage.py +0 -0
  486. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_lambda_runner.py +0 -0
  487. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_logging.py +0 -0
  488. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_login_perms.py +0 -0
  489. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_lora_rank_coverage.py +0 -0
  490. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_lora_rank_preflight.py +0 -0
  491. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_managed_config_fields.py +0 -0
  492. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_managed_hf_repo.py +0 -0
  493. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_metrics_schema_agent_contract.py +0 -0
  494. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_mig_guard.py +0 -0
  495. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_multi_gpu_gate.py +0 -0
  496. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_multimodal_training.py +0 -0
  497. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_named_reward_metrics.py +0 -0
  498. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_opd.py +0 -0
  499. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_opd_limits.py +0 -0
  500. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_opd_multiturn_eos_boundary.py +0 -0
  501. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_opd_multiturn_failure_exit.py +0 -0
  502. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_opd_replay_guard.py +0 -0
  503. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_opd_train.py +0 -0
  504. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_orchestrator_flash.py +0 -0
  505. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_packing.py +0 -0
  506. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_packing_coverage.py +0 -0
  507. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_parasail_teacher.py +0 -0
  508. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_persisted_spec_envelope.py +0 -0
  509. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_poll_helpers.py +0 -0
  510. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_preflight.py +0 -0
  511. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_prompt_budget.py +0 -0
  512. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_provider_preflight_coverage.py +0 -0
  513. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_provider_routing.py +0 -0
  514. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_provider_teardown_robustness.py +0 -0
  515. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_providers_symmetry.py +0 -0
  516. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_realized_cost.py +0 -0
  517. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_repo_cleanup.py +0 -0
  518. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_resolve_params_b.py +0 -0
  519. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_resume_on_retry.py +0 -0
  520. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_rl_train.py +0 -0
  521. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_rollout_samples.py +0 -0
  522. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_runmgmt.py +0 -0
  523. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_runpod_api_delete.py +0 -0
  524. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_runpod_key_fingerprint.py +0 -0
  525. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_runpod_key_waterfall.py +0 -0
  526. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_runtime_capsule.py +0 -0
  527. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_serve.py +0 -0
  528. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_serve_reasoning_content.py +0 -0
  529. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_server_app_coverage.py +0 -0
  530. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_server_auth_singleflight.py +0 -0
  531. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_server_billing.py +0 -0
  532. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_server_checkpoints_coverage.py +0 -0
  533. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_server_db.py +0 -0
  534. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_server_envs_coverage.py +0 -0
  535. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_server_locks_coverage.py +0 -0
  536. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_server_standalone.py +0 -0
  537. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_serving_context_preflight.py +0 -0
  538. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_serving_contract.py +0 -0
  539. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_serving_schema_coverage.py +0 -0
  540. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_sft_chunked_nll.py +0 -0
  541. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_sft_example_selection.py +0 -0
  542. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_sft_gc_off.py +0 -0
  543. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_sft_max_context.py +0 -0
  544. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_sft_startup_block.py +0 -0
  545. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_sft_train.py +0 -0
  546. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_sft_workload.py +0 -0
  547. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_spec_and_validation.py +0 -0
  548. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_spec_contract_bytes.py +0 -0
  549. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_step_floor.py +0 -0
  550. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_step_metrics.py +0 -0
  551. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_step_timing.py +0 -0
  552. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_structured_outputs.py +0 -0
  553. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_teacher_broker.py +0 -0
  554. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_teacher_encoding_contract.py +0 -0
  555. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_terminal_artifacts.py +0 -0
  556. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_thinking_config.py +0 -0
  557. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_train_context_preflight.py +0 -0
  558. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_training_controls.py +0 -0
  559. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_type_comment_prose.py +0 -0
  560. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_vast_api.py +0 -0
  561. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_vast_api_coverage.py +0 -0
  562. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_vast_offers.py +0 -0
  563. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_vast_provider_coverage.py +0 -0
  564. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_vast_runner.py +0 -0
  565. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_verified_revisions.py +0 -0
  566. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_verifiers.py +0 -0
  567. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_verl_checkpoint_export.py +0 -0
  568. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_verl_child_plugins.py +0 -0
  569. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_verl_silence_watchdog.py +0 -0
  570. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_version.py +0 -0
  571. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_vl_warmstart_adapter_keys.py +0 -0
  572. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_vram_architecture.py +0 -0
  573. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_wandb_link.py +0 -0
  574. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_wandb_naming.py +0 -0
  575. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_warmstart_adapter_download.py +0 -0
  576. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_warmstart_cross_repo.py +0 -0
  577. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_warmstart_error_attribution.py +0 -0
  578. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_weight_cache.py +0 -0
  579. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_worker_dryrun.py +0 -0
  580. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_worker_hardexit.py +0 -0
  581. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_worker_image.py +0 -0
  582. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_worker_init_heartbeat.py +0 -0
  583. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_worker_stack.py +0 -0
  584. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_worker_thinking.py +0 -0
  585. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_workflow_contracts.py +0 -0
  586. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_workload_profile.py +0 -0
  587. {freesolo_flash_dev-1.2.64 → freesolo_flash_dev-1.2.66}/tests/test_zero2_sharding_gate.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: freesolo-flash-dev
3
- Version: 1.2.64
3
+ Version: 1.2.66
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
@@ -0,0 +1,170 @@
1
+ """Bounded credential-safe diagnostic rendering."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ import re
7
+ import urllib.parse
8
+ from typing import Any
9
+
10
+ _SECRET_KEY_RE = re.compile(
11
+ r"(?i)(authorization|api[-_ ]?key|access[-_ ]?token|refresh[-_ ]?token|token|secret|password)"
12
+ r"(\s*[:=]\s*)(?:bearer\s+)?([^\s,;]+)"
13
+ )
14
+ _BEARER_RE = re.compile(r"(?i)\bbearer\s+[A-Za-z0-9._~+/=-]+")
15
+ _SECRET_ENV_SUFFIXES = ("_API_KEY", "_TOKEN", "_SECRET", "_PASSWORD")
16
+
17
+ # comma-separated env-variable names whose values are secrets regardless of naming shape: declared
18
+ # runtime secrets can carry any name (AWS_SECRET_ACCESS_KEY, FLASH_TEACHER_CAPABILITY, ...), so the
19
+ # control plane lists them explicitly in the worker env instead of relying on the suffix heuristic.
20
+ SECRET_ENV_KEYS_ENV = "FLASH_SECRET_ENV_KEYS"
21
+
22
+ # multiline secrets may appear only partially in truncated logs. register long component lines as
23
+ # needles, but ignore short common fragments such as ``}`` that would erase innocent diagnostics.
24
+ _MIN_SECRET_COMPONENT = 8
25
+ _PERCENT_ESCAPE_RE = re.compile(r"%([0-9A-Fa-f]{2})")
26
+
27
+
28
+ def _percent_pattern(needle: str) -> str:
29
+ """Regex for ``needle`` with only percent-escape hex digits matched case-insensitively."""
30
+ parts: list[str] = []
31
+ offset = 0
32
+ for match in _PERCENT_ESCAPE_RE.finditer(needle):
33
+ parts.append(re.escape(needle[offset : match.start()]))
34
+ parts.append("%")
35
+ parts.extend(
36
+ f"[{char.lower()}{char.upper()}]" if char.isalpha() else char for char in match.group(1)
37
+ )
38
+ offset = match.end()
39
+ parts.append(re.escape(needle[offset:]))
40
+ return "".join(parts)
41
+
42
+
43
+ def _bounded_pattern(needle: str) -> str:
44
+ """``needle`` anchored so it cannot match as part of a longer word.
45
+
46
+ The guard is applied per EDGE, and only where the needle's own edge is a word character. A
47
+ value with a punctuation edge already separates itself from neighbouring text, and demanding a
48
+ non-word character beyond it asks the wrong question: ``/a`` inside ``https://host/a/repo`` is
49
+ preceded by the ``t`` of ``host``, so an unconditional left guard fails and the secret prints
50
+ verbatim. ``ati`` keeps both guards and so still cannot rewrite ``authentication``.
51
+ Mirrors flash.providers._lifecycle.bootstrap_secrets._bounded_pattern.
52
+ """
53
+ escaped = re.escape(needle)
54
+ left = r"(?<!\w)" if needle[:1].isalnum() or needle[:1] == "_" else ""
55
+ right = r"(?!\w)" if needle[-1:].isalnum() or needle[-1:] == "_" else ""
56
+ return f"{left}{escaped}{right}"
57
+
58
+
59
+ _ValueMatcher = tuple[str, bool, bool]
60
+
61
+
62
+ def _configured_secrets() -> tuple[tuple[_ValueMatcher, ...], tuple[str, ...], frozenset[str]]:
63
+ """Credential matchers plus shape-only and exact raw values.
64
+
65
+ Each value matcher carries ``(needle, bounded, encoded)`` metadata. Plain values are replaced as
66
+ substrings. Bounded values are shorter than ``_MIN_SECRET_COMPONENT`` and may only match where
67
+ they are not adjacent to a word character: a 3-char global needle would mangle every diagnostic
68
+ containing those characters (the value ``ati`` rewrites ``authentication``).
69
+
70
+ A short raw candidate with no alphanumeric or underscore character is shape-only because it is
71
+ indistinguishable from ordinary punctuation. Explicit percent-octet forms remain bounded and
72
+ safely distinguishable. Keyed and bearer matching uses the known shape-only value directly.
73
+
74
+ Component lines of a multiline value keep the floor as a hard skip: a short component is
75
+ punctuation such as ``}``, not a credential.
76
+ """
77
+ declared = {
78
+ name.strip().upper()
79
+ for name in os.environ.get(SECRET_ENV_KEYS_ENV, "").split(",")
80
+ if name.strip()
81
+ }
82
+ matchers: set[_ValueMatcher] = set()
83
+ shaped: set[str] = set()
84
+ raw_values: set[str] = set()
85
+ for key, value in os.environ.items():
86
+ upper = key.upper()
87
+ if not value or not (
88
+ upper in {"AUTHORIZATION", "HF_TOKEN"}
89
+ or upper in declared
90
+ or upper.endswith(_SECRET_ENV_SUFFIXES)
91
+ ):
92
+ continue
93
+ raw_values.add(value)
94
+ candidates = {(value, False)}
95
+ encoded = urllib.parse.quote(value, safe="")
96
+ if encoded != value:
97
+ candidates.add((encoded, True))
98
+ if len(value) < _MIN_SECRET_COMPONENT and not any(
99
+ char.isalnum() or char == "_" for char in value
100
+ ):
101
+ candidates.add(("".join(f"%{byte:02X}" for byte in value.encode()), True))
102
+ if len(value) >= _MIN_SECRET_COMPONENT:
103
+ matchers.update((candidate, False, is_encoded) for candidate, is_encoded in candidates)
104
+ else:
105
+ for candidate, is_encoded in candidates:
106
+ if any(char.isalnum() or char == "_" for char in candidate):
107
+ matchers.add((candidate, True, is_encoded))
108
+ else:
109
+ shaped.add(candidate)
110
+ if "\n" in value:
111
+ for raw in value.splitlines():
112
+ if len(line := raw.strip()) >= _MIN_SECRET_COMPONENT:
113
+ matchers.add((line, False, False))
114
+ encoded_line = urllib.parse.quote(line, safe="")
115
+ if encoded_line != line:
116
+ matchers.add((encoded_line, False, True))
117
+ return tuple(matchers), tuple(shaped), frozenset(raw_values)
118
+
119
+
120
+ def sanitize_diagnostic(value: Any, *, limit: int = 2000) -> str:
121
+ """Keep useful failure context while removing credentials and bounding output."""
122
+ text = f"{type(value).__name__}: {value}" if isinstance(value, BaseException) else str(value)
123
+ matchers, shaped, raw_values = _configured_secrets()
124
+ # protect exact punctuation credentials before a separate value can erase their syntax.
125
+ for secret in sorted(shaped, key=len, reverse=True):
126
+ escaped = re.escape(secret)
127
+ text = re.sub(
128
+ rf"(?i)(authorization|api[-_ ]?key|access[-_ ]?token|refresh[-_ ]?token|token|secret|password)(\s*[:=]\s*)(?:bearer\s+)?{escaped}(?=[\s,;]|$)",
129
+ lambda match: (
130
+ "<redacted>"
131
+ if match.group(1) in raw_values
132
+ else f"{match.group(1)}{match.group(2)}<redacted>"
133
+ ),
134
+ text,
135
+ )
136
+ text = re.sub(
137
+ rf"(?i)\b(bearer)\s+{escaped}(?=[\s,;]|$)",
138
+ lambda match: "<redacted>" if match.group(1) in raw_values else "Bearer <redacted>",
139
+ text,
140
+ )
141
+ # apply both matcher types in one longest-first order so a shorter plain value cannot consume
142
+ # the prefix of a longer bounded encoded value.
143
+ for secret, is_bounded, is_encoded in sorted(
144
+ matchers, key=lambda item: len(item[0]), reverse=True
145
+ ):
146
+ if is_encoded:
147
+ pattern = _percent_pattern(secret)
148
+ if is_bounded:
149
+ left = r"(?<!\w)" if secret[:1].isalnum() or secret[:1] == "_" else ""
150
+ right = r"(?!\w)" if secret[-1:].isalnum() or secret[-1:] == "_" else ""
151
+ pattern = f"{left}{pattern}{right}"
152
+ text = re.sub(pattern, "<redacted>", text)
153
+ elif is_bounded:
154
+ text = re.sub(_bounded_pattern(secret), "<redacted>", text)
155
+ else:
156
+ text = text.replace(secret, "<redacted>")
157
+ text = _BEARER_RE.sub("Bearer <redacted>", text)
158
+ text = _SECRET_KEY_RE.sub(lambda match: f"{match.group(1)}{match.group(2)}<redacted>", text)
159
+ return text[: max(0, int(limit))]
160
+
161
+
162
+ def neutralize_control_chars(value: Any) -> str:
163
+ """Escape terminal control characters while preserving newlines as separators."""
164
+ text = str(value)
165
+ return "".join(
166
+ char
167
+ if char == "\n" or 0x20 <= ord(char) < 0x7F or ord(char) >= 0xA0
168
+ else f"\\x{ord(char):02x}"
169
+ for char in text
170
+ )
@@ -18,7 +18,7 @@ import traceback
18
18
 
19
19
  from flash._internal.diagnostics import sanitize_diagnostic
20
20
  from flash.adapters.fused_experts import lora_target_parameters
21
- from flash.core.spec import FIXED_SEED, load_job_spec_from_env
21
+ from flash.core.spec import FIXED_SEED, gpu_count_of, load_job_spec_from_env
22
22
  from flash.engine.result.accounting import RunMetrics
23
23
  from flash.engine.worker.backend_common import collect_ray_failure_logs
24
24
  from flash.engine.worker.entry.opd import run_opd
@@ -80,7 +80,7 @@ from flash.engine.worker.perf import (
80
80
  grad_checkpointing_on,
81
81
  grpo_use_reentrant,
82
82
  is_cuda_oom,
83
- preflight_free_vram,
83
+ preflight_gpu_occupancy,
84
84
  wait_for_gpu,
85
85
  )
86
86
  from flash.engine.worker.runtime.kernel_warmup import _current_cuda_sm, load_mega_cache
@@ -221,22 +221,16 @@ def _worker_failure_flags(exc: BaseException) -> dict[str, bool]:
221
221
  return {"retriable": retriable, "oom": (not retriable and is_cuda_oom(exc))}
222
222
 
223
223
 
224
- def _preflight_free_vram_for_spec() -> None:
225
- """Reject a card that arrived already occupied by another tenant.
224
+ def _preflight_gpu_occupancy_for_spec() -> None:
225
+ """Screen every GPU in the allocator-resolved worker allocation for substantial occupancy.
226
226
 
227
- Nothing about the spec is read. An earlier draft re-derived the run's requirement here and
228
- compared free bytes against it, which is a second sizing model competing with the allocator's
229
- and wrong in both directions -- see ``preflight_free_vram``. Occupancy needs no requirement, so
230
- it runs on any shape without reimplementing ``combined_vram_gb``'s non-linear multi-card fit.
227
+ The allocator stamps the chosen count onto ``JOB_SPEC`` before provider launch, so this passes
228
+ only the cards rented for this worker. It does not re-derive required VRAM or claim exact fit.
231
229
 
232
- It samples device 0 only. On a multi-card node that leaves a tenant sitting on device 3 alone
233
- undetected, which is a gap and not a false alarm -- device 0 occupancy is still evidence of a
234
- shared host.
235
-
236
- Must stay the first CUDA-adjacent call in boot: the reading is only trustworthy while this
230
+ This must stay the first CUDA-adjacent call in boot. The reading is trustworthy only while this
237
231
  process has no context of its own, and ``_force_fla_triton_gdn_on_sm100`` below creates one.
238
232
  """
239
- preflight_free_vram()
233
+ preflight_gpu_occupancy(gpu_count_of(JOB_SPEC))
240
234
 
241
235
 
242
236
  THINKING = JOB_SPEC.thinking if JOB_SPEC else False
@@ -347,14 +341,14 @@ def _run_worker_mode() -> None:
347
341
  # FIRST, and specifically before `_force_fla_triton_gdn_on_sm100`: that reads
348
342
  # `get_device_capability`, which initializes CUDA in this process, and from that moment the
349
343
  # driver's "used" includes our own context with no sound way to subtract it -- the occupancy
350
- # check declines to run rather than guess (see `preflight_free_vram`), so calling it later means
351
- # never calling it at all. This is also before `_ensure_fla_fastpath_on_hopper`, whose repair
344
+ # check declines to run rather than guess (see `preflight_gpu_occupancy`), so calling it later
345
+ # means never calling it at all. this is also before `_ensure_fla_fastpath_on_hopper`, whose repair
352
346
  # path runs pip installs with 600s timeouts: a card handed over with a co-tenant's ~18GB still
353
347
  # resident fails the run either way, and the only question is whether that happens now or after
354
348
  # dependency repair, the model download and FSDP init have spent paid GPU on the same
355
349
  # conclusion. NVML answers without a context, so nothing here dirties the reading for the code
356
350
  # below.
357
- _preflight_free_vram_for_spec()
351
+ _preflight_gpu_occupancy_for_spec()
358
352
  # run before model imports: sm100 tilelang GDN computes wrong gradients, so use Triton.
359
353
  _force_fla_triton_gdn_on_sm100()
360
354
  _ensure_fla_fastpath_on_hopper()
@@ -28,7 +28,7 @@ from flash.engine.worker.perf.lifecycle import (
28
28
  RetriableInfraError,
29
29
  free_vram_gb,
30
30
  is_cuda_oom,
31
- preflight_free_vram,
31
+ preflight_gpu_occupancy,
32
32
  total_vram_gb,
33
33
  wait_for_gpu,
34
34
  )
@@ -403,7 +403,7 @@ __all__ = [
403
403
  "grad_checkpointing_on",
404
404
  "grpo_use_reentrant",
405
405
  "is_cuda_oom",
406
- "preflight_free_vram",
406
+ "preflight_gpu_occupancy",
407
407
  "total_vram_gb",
408
408
  "wait_for_gpu",
409
409
  ]
@@ -34,36 +34,31 @@ class RetriableInfraError(RuntimeError):
34
34
 
35
35
 
36
36
  class DirtyGpuError(RetriableInfraError):
37
- """The allocated card arrived with too little free VRAM to run on.
38
-
39
- A RetriableInfraError, deliberately not an OOM. The two recover differently and only one of them
40
- is right here: an OOM means the run does not fit the card and retries on a BIGGER one, spending
41
- from a small dedicated OOM budget. A dirty card means the run fits fine and the card was already
42
- occupied -- a co-tenant in another container, or a previous tenant's leak. Escalating size for
43
- that pays more for a card that can be just as dirty, and burns an OOM retry proving it.
44
-
45
- Infra retry reallocates instead: ``_handle_failure`` records the provider in ``failed_providers``
46
- and the shape in ``tried_classes``, so the next attempt prefers a DIFFERENT provider, then an
47
- untried shape, before clamping back. That is the right preference order for this failure --
48
- co-tenancy is a property of the host pool that handed the instance out, not of the run -- but it
49
- is a preference, not a guarantee, so nothing here promises which card comes back.
37
+ """An allocated GPU arrived with substantial pre-existing occupancy.
38
+
39
+ This is retriable infrastructure, deliberately not an OOM. An OOM means the run does not fit
40
+ and retries on a larger card. Substantial boot-time occupancy instead calls for a fresh
41
+ allocation, because a larger card can arrive just as occupied. This error does not claim that an
42
+ accepted card has enough free VRAM for the run: occupancy at or below 5%, unreadable NVML, and
43
+ invalid readings remain fail-open limits of the best-effort screen.
50
44
  """
51
45
 
52
46
 
53
- def _nvml_memory_gb() -> tuple[float, float] | None:
54
- """``(free, total)`` on device 0 in GB straight from NVML, or None if NVML will not answer.
47
+ def _nvml_memory_gb(device_index: int = 0) -> tuple[float, float] | None:
48
+ """``(free, total)`` for one device in GB from NVML, or None if NVML will not answer.
55
49
 
56
- NVML, not ``torch.cuda.mem_get_info``: the torch call needs a CUDA context and CREATES one if the
57
- process has none, so the act of measuring adds our own few hundred MB to the number being
58
- measured. NVML queries the driver without initializing CUDA in this process, which is what lets
59
- the boot reading be taken while the card is still provably untouched by us.
50
+ NVML, not ``torch.cuda.mem_get_info``: the torch call needs a CUDA context and creates one if the
51
+ process has none, so the act of measuring adds our own memory to the number being measured. NVML
52
+ queries the driver without initializing CUDA in this process. Device 0 remains the default for
53
+ the diagnostic helpers that expose its free and total memory.
60
54
  """
61
55
  try:
62
56
  import pynvml
63
57
 
64
58
  pynvml.nvmlInit()
65
59
  try:
66
- info = pynvml.nvmlDeviceGetMemoryInfo(pynvml.nvmlDeviceGetHandleByIndex(0))
60
+ handle = pynvml.nvmlDeviceGetHandleByIndex(device_index)
61
+ info = pynvml.nvmlDeviceGetMemoryInfo(handle)
67
62
  return float(info.free) / (1024**3), float(info.total) / (1024**3)
68
63
  finally:
69
64
  with contextlib.suppress(Exception):
@@ -110,76 +105,44 @@ def total_vram_gb() -> float | None:
110
105
  return None if reading is None else reading[1]
111
106
 
112
107
 
113
- def preflight_free_vram(*, max_occupied_fraction: float = 0.05) -> None:
114
- """Fail fast when the allocated card arrives already occupied by somebody else.
115
-
116
- Flash sizes the run, asks the provider for a card that fits, and then trains on whatever comes
117
- back without ever checking that the memory is FREE. A real RTX 4090 arrived with
118
- ``total=22.5 used=18.6 free=3.4``, only 0.486 GB of it owned by any process in this container:
119
- ~18 GB was a co-tenant in another container. The number was already in the first heartbeat,
120
- before any work -- recorded and not acted on -- so the run downloaded the model and built FSDP
121
- for ~80s of paid GPU before dying on an OOM that was knowable at boot.
122
-
123
- Measured as OCCUPANCY (``used/total`` as the driver reports it), not against a requirement.
124
- Re-deriving "what this run needs" here would be a second sizing model competing with the
125
- allocator's, and it loses both ways: the allocator sizes SFT from profile-measured knobs
126
- (``_overridden_train``) that reduce an authored batch 8 to the executed batch 1, so recomputing
127
- from the authored spec demands more than the card was rented for; and a run sized exactly at a
128
- catalog tier (24 GB) can exceed a real card's usable total (22.5 GB on a 4090), which no amount
129
- of free memory can ever satisfy. Both reject a perfectly clean card and retry until the infra
130
- budget is gone -- strictly worse than the OOM this exists to prevent.
131
-
132
- Occupancy has neither failure mode: it needs no requirement, no profile, and no catalog number.
133
- An empty card reads ~0 whatever is scheduled on it, so the threshold can sit near zero rather
134
- than being padded to cover a requirement it never consults. 5% is the driver's own reserve plus
135
- slack; the observed dirty card was at 83% with 0.486 GB attributable to us.
136
-
137
- The floor is low BECAUSE the check is occupancy: a loose threshold has to be justified against
138
- the biggest run that could be scheduled, and a 5 GB co-tenant that leaves a 20 GB run 17.5 GB on
139
- a 22.5 GB card is 22% occupied and fatal. Sizing the threshold to survive that means re-deriving
140
- the requirement, which is the failure above. Refusing every card with a stranger on it needs no
141
- requirement and covers the close-fitting case too.
142
-
143
- A threshold that low only works if none of the used memory is OURS, and that is established by
144
- WHEN the reading is taken, not by trying to attribute it afterwards. Attribution was tried and
145
- cannot work here: ``nvidia-smi --query-compute-apps`` reports HOST pids, while the worker
146
- container runs with a private pid namespace (``docker run`` in ``providers/_lifecycle/instance``
147
- passes no ``--pid=host``), so testing ``/proc/<pid>`` inside the container is not an ownership
148
- test in either direction -- our own rows fail it and get counted as a stranger's, and under
149
- ``--pid=host`` a real co-tenant passes it and gets credited to us, silently waving through the
150
- exact card this exists to refuse.
151
-
152
- So the check simply declines to run once this process has a CUDA context, which makes WHEN it
153
- runs the whole design. There is exactly one call site, ``_preflight_free_vram_for_spec`` at the
154
- top of ``_run_worker_mode``, and it is placed before ``_force_fla_triton_gdn_on_sm100`` because
155
- that reads ``get_device_capability`` and creates the process's first context. Calling from
156
- anywhere below that point is not a weaker check, it is no check at all: the guard above returns
157
- immediately and the card is never read. A single early call site is therefore the invariant, not
158
- an omission -- a later retry could only run after CUDA came up, when the reading is already
159
- unusable. That also means one NVML failure at boot is one lost reading, not a lost run: the
160
- guard below returns and training proceeds exactly as it did before this check existed.
108
+ def preflight_gpu_occupancy(gpu_count: int, *, max_occupied_fraction: float = 0.05) -> None:
109
+ """Screen each allocated GPU for substantial occupancy before CUDA initialization.
110
+
111
+ The worker reads exactly the allocator-resolved device indices ``range(gpu_count)`` through NVML.
112
+ An unreadable device or a non-positive total is skipped without hiding later allocated devices.
113
+ If any valid reading exceeds 5% occupancy, the allocation is rejected as retriable
114
+ infrastructure after every allocated device has been inspected.
115
+
116
+ This is a best-effort occupancy boundary, not an exact-fit guarantee. It deliberately does not
117
+ reconstruct the allocator's run requirement. Occupancy at or below 5%, unreadable NVML, and
118
+ invalid readings remain accepted. Once this process has initialized CUDA, the whole screen is
119
+ fail-open because the driver reading includes memory owned by this process with no sound way to
120
+ subtract it.
161
121
  """
162
122
  if cuda_is_initialized():
163
- # some of `used` would be ours and there is no sound way to tell how much. a check that
164
- # cannot distinguish our context from a co-tenant would either false-reject clean cards or
165
- # need a threshold too loose to catch the tenant it exists for. staying silent is correct:
166
- # the boot call already read this card while it was provably untouched.
123
+ # some of `used` would be ours and there is no sound way to tell how much
167
124
  return
168
- reading = _nvml_memory_gb()
169
- if reading is None:
170
- # NVML would not answer. somebody else's failure to report, not evidence of a dirty card --
171
- # training fails soon enough with a better message.
172
- return
173
- free, total = reading
174
- if total <= 0:
175
- return
176
- used = max(0.0, total - free)
177
- if used <= total * max_occupied_fraction:
125
+
126
+ first_dirty: tuple[int, float, float] | None = None
127
+ for device_index in range(gpu_count):
128
+ reading = _nvml_memory_gb(device_index)
129
+ if reading is None:
130
+ # one unreadable device is not evidence about any later allocated device
131
+ continue
132
+ free, total = reading
133
+ if total <= 0:
134
+ continue
135
+ used = max(0.0, total - free)
136
+ if used > total * max_occupied_fraction and first_dirty is None:
137
+ first_dirty = (device_index, used, total)
138
+
139
+ if first_dirty is None:
178
140
  return
141
+ device_index, used, total = first_dirty
179
142
  raise DirtyGpuError(
180
- f"allocated GPU has {used:.1f} GB of {total:.1f} GB ({used / total:.0%}) already in use "
181
- "before this run has touched it; the card is occupied by another tenant or a previous "
182
- "tenant's leak, so retrying on a freshly allocated instance"
143
+ f"allocated GPU device {device_index} has {used:.1f} GB of {total:.1f} GB "
144
+ f"({used / total:.0%}) already in use before this run has touched it; the card is occupied "
145
+ "by another tenant or a previous tenant's leak, so retrying on a freshly allocated instance"
183
146
  )
184
147
 
185
148
 
@@ -22,6 +22,22 @@ _SECRET_RE = re.compile(
22
22
  # component lines are registered as needles too; the floor keeps a common fragment such as ``}``
23
23
  # from erasing innocent output. Mirrors flash._internal.diagnostics.
24
24
  _MIN_SECRET_COMPONENT = 8
25
+ _PERCENT_ESCAPE_RE = re.compile(r"%([0-9A-Fa-f]{2})")
26
+
27
+
28
+ def _percent_pattern(needle: str) -> str:
29
+ """Regex for ``needle`` with only percent-escape hex digits matched case-insensitively."""
30
+ parts: list[str] = []
31
+ offset = 0
32
+ for match in _PERCENT_ESCAPE_RE.finditer(needle):
33
+ parts.append(re.escape(needle[offset : match.start()]))
34
+ parts.append("%")
35
+ parts.extend(
36
+ f"[{char.lower()}{char.upper()}]" if char.isalpha() else char for char in match.group(1)
37
+ )
38
+ offset = match.end()
39
+ parts.append(re.escape(needle[offset:]))
40
+ return "".join(parts)
25
41
 
26
42
 
27
43
  def _bounded_pattern(needle: str) -> str:
@@ -39,37 +55,86 @@ def _bounded_pattern(needle: str) -> str:
39
55
  return f"{left}{escaped}{right}"
40
56
 
41
57
 
42
- def _needles(values: set[str]) -> tuple[set[str], set[str]]:
43
- """The ``(plain, bounded)`` needle sets for ``values``.
58
+ _ValueMatcher = tuple[str, bool, bool]
59
+
60
+
61
+ def _needles(values: set[str]) -> tuple[set[_ValueMatcher], set[str]]:
62
+ """The typed value matchers and shape-only needles for ``values``.
44
63
 
45
- plain = replaced as a substring. bounded = values under the floor, replaced only where not
46
- adjacent to a word character: dropping them leaked them verbatim, and replacing them plainly
47
- would rewrite innocent text (``ati`` inside ``authentication``). encoded forms are registered
48
- too. component lines of a MULTILINE value keep the floor as a hard skip -- a short one is
64
+ each value matcher carries ``(needle, bounded, encoded)`` metadata. plain needles are replaced as
65
+ substrings. bounded needles are values under the floor, replaced only where not adjacent to a word
66
+ character. a short raw candidate with no alphanumeric or underscore character is shape-only
67
+ because it is indistinguishable from ordinary punctuation; explicit percent-octet forms remain
68
+ bounded. component lines of a multiline value keep the floor as a hard skip: a short one is
49
69
  punctuation such as ``}``, not a credential.
50
70
  """
51
- plain: set[str] = set()
52
- bounded: set[str] = set()
71
+ matchers: set[_ValueMatcher] = set()
72
+ shaped: set[str] = set()
53
73
  for secret in values:
54
- target = plain if len(secret) >= _MIN_SECRET_COMPONENT else bounded
55
- target.update({secret, urllib.parse.quote(secret, safe="")})
74
+ candidates = {(secret, False)}
75
+ encoded = urllib.parse.quote(secret, safe="")
76
+ if encoded != secret:
77
+ candidates.add((encoded, True))
78
+ if len(secret) < _MIN_SECRET_COMPONENT and not any(
79
+ char.isalnum() or char == "_" for char in secret
80
+ ):
81
+ candidates.add(("".join(f"%{byte:02X}" for byte in secret.encode()), True))
82
+ if len(secret) >= _MIN_SECRET_COMPONENT:
83
+ matchers.update((candidate, False, is_encoded) for candidate, is_encoded in candidates)
84
+ else:
85
+ for candidate, is_encoded in candidates:
86
+ if any(char.isalnum() or char == "_" for char in candidate):
87
+ matchers.add((candidate, True, is_encoded))
88
+ else:
89
+ shaped.add(candidate)
56
90
  if "\n" in secret:
57
91
  for raw in secret.splitlines():
58
92
  if len(line := raw.strip()) >= _MIN_SECRET_COMPONENT:
59
- plain.update({line, urllib.parse.quote(line, safe="")})
60
- return plain, bounded
93
+ matchers.add((line, False, False))
94
+ encoded_line = urllib.parse.quote(line, safe="")
95
+ if encoded_line != line:
96
+ matchers.add((encoded_line, False, True))
97
+ return matchers, shaped
61
98
 
62
99
 
63
100
  def _redact_values(text: str, values: set[str]) -> str:
64
101
  """Replace every credential value in ``text``; see ``_needles`` for how each form is matched.
65
102
 
66
- Longest-first, so one secret containing another cannot leave a suffix of the longer one behind.
103
+ Longest-first across both matcher types, so one secret containing another cannot leave a suffix
104
+ of the longer one behind.
67
105
  """
68
- plain, bounded = _needles(values)
69
- for needle in sorted(plain, key=len, reverse=True):
70
- text = text.replace(needle, "<redacted>")
71
- for needle in sorted(bounded, key=len, reverse=True):
72
- text = re.sub(_bounded_pattern(needle), "<redacted>", text)
106
+ matchers, shaped = _needles(values)
107
+ # protect exact punctuation credentials before a separate value can erase their syntax.
108
+ for needle in sorted(shaped, key=len, reverse=True):
109
+ escaped = re.escape(needle)
110
+ text = re.sub(
111
+ rf"(?i)(authorization|api[-_ ]?key|access[-_ ]?token|token|secret|password)(\s*[:=]\s*)(?:bearer\s+)?{escaped}(?=[\s,;]|$)",
112
+ lambda match: (
113
+ "<redacted>"
114
+ if match.group(1) in values
115
+ else f"{match.group(1)}{match.group(2)}<redacted>"
116
+ ),
117
+ text,
118
+ )
119
+ text = re.sub(
120
+ rf"(?i)\b(bearer)\s+{escaped}(?=[\s,;]|$)",
121
+ lambda match: "<redacted>" if match.group(1) in values else "Bearer <redacted>",
122
+ text,
123
+ )
124
+ for needle, is_bounded, is_encoded in sorted(
125
+ matchers, key=lambda item: len(item[0]), reverse=True
126
+ ):
127
+ if is_encoded:
128
+ pattern = _percent_pattern(needle)
129
+ if is_bounded:
130
+ left = r"(?<!\w)" if needle[:1].isalnum() or needle[:1] == "_" else ""
131
+ right = r"(?!\w)" if needle[-1:].isalnum() or needle[-1:] == "_" else ""
132
+ pattern = f"{left}{pattern}{right}"
133
+ text = re.sub(pattern, "<redacted>", text)
134
+ elif is_bounded:
135
+ text = re.sub(_bounded_pattern(needle), "<redacted>", text)
136
+ else:
137
+ text = text.replace(needle, "<redacted>")
73
138
  return text
74
139
 
75
140