freesolo-flash-dev 1.2.65__tar.gz → 1.2.67__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.65 → freesolo_flash_dev-1.2.67}/PKG-INFO +1 -1
  2. freesolo_flash_dev-1.2.67/flash/_internal/diagnostics.py +170 -0
  3. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/sft_train.py +13 -2
  4. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/_lifecycle/bootstrap_secrets.py +83 -18
  5. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/runpod/serverless/endpoints.py +96 -34
  6. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/runner/supervise/seed_submission.py +21 -15
  7. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/pyproject.toml +2 -2
  8. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_backend_common.py +81 -0
  9. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_envs_coverage.py +6 -0
  10. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_flash_worker.py +210 -12
  11. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_instance_bootstrap_coverage.py +59 -0
  12. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_opd_resume_safety.py +96 -21
  13. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_opd_train.py +47 -0
  14. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_rl_train.py +88 -0
  15. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_sft_train.py +72 -1
  16. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/uv.lock +1 -1
  17. freesolo_flash_dev-1.2.65/flash/_internal/diagnostics.py +0 -106
  18. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/.dockerignore +0 -0
  19. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/.env.example +0 -0
  20. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/.github/CODEOWNERS +0 -0
  21. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  22. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  23. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  24. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  25. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/.github/dependabot.yml +0 -0
  26. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/.github/workflows/auto-rebake.yml +0 -0
  27. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/.github/workflows/bake-kernel-cache.yml +0 -0
  28. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/.github/workflows/ci.yml +0 -0
  29. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/.github/workflows/main-source-guard.yml +0 -0
  30. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/.github/workflows/notify-tests-repo.yml +0 -0
  31. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/.github/workflows/publish-dev.yml +0 -0
  32. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/.github/workflows/publish-image.yml +0 -0
  33. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/.github/workflows/publish.yml +0 -0
  34. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/.github/workflows/version-parity.yml +0 -0
  35. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/.github/workflows/worker-image.yml +0 -0
  36. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/.gitignore +0 -0
  37. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/CHANGELOG.md +0 -0
  38. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/CODE_OF_CONDUCT.md +0 -0
  39. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/CONTRIBUTING.md +0 -0
  40. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/Dockerfile +0 -0
  41. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/Dockerfile.worker +0 -0
  42. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/LICENSE +0 -0
  43. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/NOTICE +0 -0
  44. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/README.md +0 -0
  45. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/SECURITY.md +0 -0
  46. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/SELF_HOSTING.md +0 -0
  47. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/build/kernel_cache/.gitignore +0 -0
  48. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/build/kernel_cache/.keep +0 -0
  49. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/deploy/infisical/README.md +0 -0
  50. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/deploy/infisical/entrypoint.sh +0 -0
  51. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/docker/Dockerfile.kernelcache +0 -0
  52. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/docker/Dockerfile.kernelcache.relayer +0 -0
  53. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/docker/bake_kernel_cache.py +0 -0
  54. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/docker/bake_pod_entry.py +0 -0
  55. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/docker/extract_cudart_fix.py +0 -0
  56. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/docker/kernel_fingerprint.py +0 -0
  57. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/docker/make_rp_handler.py +0 -0
  58. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/__init__.py +0 -0
  59. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/_internal/__init__.py +0 -0
  60. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/_internal/channel.py +0 -0
  61. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/_internal/fileio.py +0 -0
  62. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/_internal/logging.py +0 -0
  63. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/_internal/paths.py +0 -0
  64. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/adapters/__init__.py +0 -0
  65. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/adapters/artifacts.py +0 -0
  66. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/adapters/fused_experts.py +0 -0
  67. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/adapters/lora_rank.py +0 -0
  68. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/cli/__init__.py +0 -0
  69. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/cli/__main__.py +0 -0
  70. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/cli/commands/__init__.py +0 -0
  71. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/cli/commands/deploy.py +0 -0
  72. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/cli/commands/env/__init__.py +0 -0
  73. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/cli/commands/env/episode.py +0 -0
  74. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/cli/commands/env/eval.py +0 -0
  75. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/cli/commands/env/eval_args.py +0 -0
  76. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/cli/commands/env/imports.py +0 -0
  77. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/cli/commands/env/list.py +0 -0
  78. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/cli/commands/env/push.py +0 -0
  79. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/cli/commands/env/retained.py +0 -0
  80. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/cli/commands/env/setup.py +0 -0
  81. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/cli/commands/env/setup_wandb.py +0 -0
  82. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/cli/commands/env/test.py +0 -0
  83. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/cli/commands/env/test_evaluations.py +0 -0
  84. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/cli/commands/env/test_params.py +0 -0
  85. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/cli/commands/env/test_warnings.py +0 -0
  86. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/cli/commands/prompt_budget.py +0 -0
  87. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/cli/commands/traces.py +0 -0
  88. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/cli/commands/train_cost.py +0 -0
  89. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/cli/scaffold/TRAINING.md +0 -0
  90. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/cli/scaffold/__init__.py +0 -0
  91. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/cli/ui/__init__.py +0 -0
  92. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/cli/ui/cost.py +0 -0
  93. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/cli/ui/env_panels.py +0 -0
  94. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/cli/ui/heartbeat.py +0 -0
  95. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/cli/ui/render.py +0 -0
  96. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/cli/ui/tables.py +0 -0
  97. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/cli/ui/tty.py +0 -0
  98. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/client/__init__.py +0 -0
  99. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/client/config.py +0 -0
  100. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/client/freesolo_api.py +0 -0
  101. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/client/http.py +0 -0
  102. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/client/runtime_secrets.py +0 -0
  103. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/client/shapes.py +0 -0
  104. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/client/specs.py +0 -0
  105. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/client/streaming.py +0 -0
  106. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/content/__init__.py +0 -0
  107. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/content/multimodal.py +0 -0
  108. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/content/structured_outputs.py +0 -0
  109. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/content/thinking.py +0 -0
  110. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/core/__init__.py +0 -0
  111. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/core/catalog.py +0 -0
  112. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/core/spec.py +0 -0
  113. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/core/spec_persistence.py +0 -0
  114. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/cost/__init__.py +0 -0
  115. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/cost/analytical.py +0 -0
  116. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/cost/facts.py +0 -0
  117. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/cost/spec.py +0 -0
  118. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/cost/types.py +0 -0
  119. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/__init__.py +0 -0
  120. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/huggingface.py +0 -0
  121. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/plan/__init__.py +0 -0
  122. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/plan/kv_sizing.py +0 -0
  123. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/plan/model_config_probe.py +0 -0
  124. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/plan/prompt_budget.py +0 -0
  125. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/plan/recipe.py +0 -0
  126. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/plan/steps.py +0 -0
  127. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/plan/vram.py +0 -0
  128. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/profiling/__init__.py +0 -0
  129. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/profiling/dataset_profile.py +0 -0
  130. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/profiling/image_tokens.py +0 -0
  131. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/profiling/reasoning_render.py +0 -0
  132. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/profiling/sft_image_rows.py +0 -0
  133. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/profiling/sft_workload.py +0 -0
  134. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/profiling/tokenizer.py +0 -0
  135. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/profiling/workload_profile.py +0 -0
  136. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/result/__init__.py +0 -0
  137. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/result/accounting.py +0 -0
  138. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/result/rollout_samples.py +0 -0
  139. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/__init__.py +0 -0
  140. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/__main__.py +0 -0
  141. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/backend_common.py +0 -0
  142. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/entry/__init__.py +0 -0
  143. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/entry/opd.py +0 -0
  144. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/entry/rl.py +0 -0
  145. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/entry/sft.py +0 -0
  146. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/io/__init__.py +0 -0
  147. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/io/heartbeat.py +0 -0
  148. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/io/hf.py +0 -0
  149. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/io/prefetch.py +0 -0
  150. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/io/wandb_log.py +0 -0
  151. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/model/__init__.py +0 -0
  152. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/model/adapter.py +0 -0
  153. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/model/chatml_mask.py +0 -0
  154. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/model/decoding.py +0 -0
  155. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/model/lora.py +0 -0
  156. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/model/packing.py +0 -0
  157. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/opd_train.py +0 -0
  158. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/opd_train_runner.py +0 -0
  159. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/perf/__init__.py +0 -0
  160. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/perf/diagnostics.py +0 -0
  161. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/perf/lifecycle.py +0 -0
  162. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/perf/liger.py +0 -0
  163. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/perf/memory.py +0 -0
  164. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/rl_train.py +0 -0
  165. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/rl_train_runner.py +0 -0
  166. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/runtime/__init__.py +0 -0
  167. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/runtime/kernel_warmup.py +0 -0
  168. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/runtime/pkg_proxy.py +0 -0
  169. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/runtime/rng.py +0 -0
  170. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/score_batcher.py +0 -0
  171. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/sft_train_runner.py +0 -0
  172. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/teacher/__init__.py +0 -0
  173. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/teacher/client.py +0 -0
  174. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/teacher/encoding.py +0 -0
  175. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/teacher/tokenizer_align.py +0 -0
  176. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/__init__.py +0 -0
  177. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/core/__init__.py +0 -0
  178. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/core/checkpoint_lifecycle.py +0 -0
  179. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/core/child/__init__.py +0 -0
  180. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/core/child/glue.py +0 -0
  181. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/core/child/runtime.py +0 -0
  182. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/core/step_timing.py +0 -0
  183. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/finalize.py +0 -0
  184. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/opd/__init__.py +0 -0
  185. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/opd/batching.py +0 -0
  186. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/opd/bridge.py +0 -0
  187. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/opd/bridge_failures.py +0 -0
  188. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/opd/child/__init__.py +0 -0
  189. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/opd/child/bridge.py +0 -0
  190. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/opd/child/entry.py +0 -0
  191. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/opd/child/multiturn.py +0 -0
  192. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/opd/child/plugin.py +0 -0
  193. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/opd/child/replay_guard.py +0 -0
  194. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/opd/child/runtime.py +0 -0
  195. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/opd/child/structured.py +0 -0
  196. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/opd/failures.py +0 -0
  197. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/opd/gkd.py +0 -0
  198. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/opd/multiturn_validation.py +0 -0
  199. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/opd/overrides.py +0 -0
  200. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/opd/prompts.py +0 -0
  201. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/opd/reporting.py +0 -0
  202. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/opd/scoring.py +0 -0
  203. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/opd/state.py +0 -0
  204. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/opd/validation.py +0 -0
  205. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/rl/__init__.py +0 -0
  206. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/rl/checkpoints.py +0 -0
  207. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/rl/child/__init__.py +0 -0
  208. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/rl/child/entry.py +0 -0
  209. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/rl/child/multiturn.py +0 -0
  210. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/rl/child/patches.py +0 -0
  211. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/rl/child/plugin.py +0 -0
  212. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/rl/config.py +0 -0
  213. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/rl/inputs.py +0 -0
  214. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/rl/multi_turn.py +0 -0
  215. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/rl/reward_module.py +0 -0
  216. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/rl/scoring.py +0 -0
  217. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/rl/single_turn.py +0 -0
  218. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/rl/verl_config.py +0 -0
  219. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/sft/__init__.py +0 -0
  220. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/sft/checkpoints.py +0 -0
  221. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/sft/child/entry.py +0 -0
  222. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/sft/child/plugin.py +0 -0
  223. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/train/sft/config.py +0 -0
  224. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/verl/__init__.py +0 -0
  225. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/verl/capabilities.py +0 -0
  226. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/verl/checkpoints.py +0 -0
  227. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/verl/child_io.py +0 -0
  228. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/verl/diagnostics.py +0 -0
  229. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/verl/parallelism.py +0 -0
  230. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker/verl/parent_work.py +0 -0
  231. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/engine/worker_entrypoint.py +0 -0
  232. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/envs/__init__.py +0 -0
  233. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/envs/adapter.py +0 -0
  234. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/envs/base.py +0 -0
  235. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/envs/cache_security.py +0 -0
  236. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/envs/dataset_selection.py +0 -0
  237. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/envs/evaluations.py +0 -0
  238. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/envs/identity.py +0 -0
  239. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/envs/loader.py +0 -0
  240. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/envs/namespace_listing.py +0 -0
  241. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/envs/package/__init__.py +0 -0
  242. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/envs/package/limits.py +0 -0
  243. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/envs/package/unpack.py +0 -0
  244. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/envs/pull.py +0 -0
  245. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/__init__.py +0 -0
  246. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/_lifecycle/__init__.py +0 -0
  247. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/_lifecycle/auth.py +0 -0
  248. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/_lifecycle/bootstrap.py +0 -0
  249. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/_lifecycle/bootstrap_console.py +0 -0
  250. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/_lifecycle/bootstrap_pip.py +0 -0
  251. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/_lifecycle/deadline.py +0 -0
  252. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/_lifecycle/host/__init__.py +0 -0
  253. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/_lifecycle/host/deadline_sleep.py +0 -0
  254. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/_lifecycle/host/failmark.py +0 -0
  255. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/_lifecycle/host/hostlog.py +0 -0
  256. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/_lifecycle/http.py +0 -0
  257. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/_lifecycle/instance.py +0 -0
  258. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/_lifecycle/poll.py +0 -0
  259. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/_lifecycle/poll_instance.py +0 -0
  260. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/_lifecycle/provider.py +0 -0
  261. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/_lifecycle/terminal_artifacts.py +0 -0
  262. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/_lifecycle/worker.py +0 -0
  263. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/allocator.py +0 -0
  264. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/artifacts/__init__.py +0 -0
  265. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/artifacts/hf.py +0 -0
  266. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/artifacts/preload_runpod.py +0 -0
  267. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/artifacts/weight_cache.py +0 -0
  268. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/base.py +0 -0
  269. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/fit_errors.py +0 -0
  270. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/lambda_/__init__.py +0 -0
  271. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/lambda_/api.py +0 -0
  272. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/lambda_/auth.py +0 -0
  273. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/lambda_/gpus.py +0 -0
  274. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/lambda_/jobs/__init__.py +0 -0
  275. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/lambda_/jobs/builders.py +0 -0
  276. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/lambda_/jobs/reap.py +0 -0
  277. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/lambda_/preflight.py +0 -0
  278. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/lambda_/pricing.py +0 -0
  279. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/preflight.py +0 -0
  280. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/realized.py +0 -0
  281. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/runpod/__init__.py +0 -0
  282. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/runpod/api.py +0 -0
  283. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/runpod/auth.py +0 -0
  284. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/runpod/cost.py +0 -0
  285. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/runpod/gpus.py +0 -0
  286. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/runpod/job_execution.py +0 -0
  287. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/runpod/jobs.py +0 -0
  288. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/runpod/preflight.py +0 -0
  289. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/runpod/pricing.py +0 -0
  290. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/runpod/resources.py +0 -0
  291. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/runpod/serverless/__init__.py +0 -0
  292. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/sharding.py +0 -0
  293. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/vast/__init__.py +0 -0
  294. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/vast/api.py +0 -0
  295. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/vast/auth.py +0 -0
  296. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/vast/jobs/__init__.py +0 -0
  297. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/vast/jobs/builders.py +0 -0
  298. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/vast/preflight.py +0 -0
  299. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/providers/vast/pricing.py +0 -0
  300. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/py.typed +0 -0
  301. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/runner/__init__.py +0 -0
  302. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/runner/artifacts.py +0 -0
  303. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/runner/attempts.py +0 -0
  304. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/runner/costs.py +0 -0
  305. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/runner/deadlines.py +0 -0
  306. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/runner/preparation.py +0 -0
  307. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/runner/reconciliation.py +0 -0
  308. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/runner/results/__init__.py +0 -0
  309. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/runner/results/checkpoints.py +0 -0
  310. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/runner/results/verified_revisions.py +0 -0
  311. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/runner/status.py +0 -0
  312. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/runner/submit.py +0 -0
  313. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/runner/supervise/__init__.py +0 -0
  314. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/runner/supervise/attach.py +0 -0
  315. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/runner/supervise/deploy.py +0 -0
  316. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/runner/supervise/lifecycle.py +0 -0
  317. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/runner/supervise/recovery.py +0 -0
  318. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/runner/supervise/retry_decision.py +0 -0
  319. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/runner/supervise/transitions.py +0 -0
  320. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/runner/weight_cache.py +0 -0
  321. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/runtime_capsule/__init__.py +0 -0
  322. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/runtime_capsule/build.py +0 -0
  323. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/runtime_capsule/manifest.py +0 -0
  324. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/runtime_capsule/profiles.py +0 -0
  325. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/schema/__init__.py +0 -0
  326. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/schema/fields.py +0 -0
  327. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/serve/__init__.py +0 -0
  328. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/serve/adapter_check.py +0 -0
  329. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/serve/deploy.py +0 -0
  330. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/serve/errors.py +0 -0
  331. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/serve/export.py +0 -0
  332. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/serve/preflight.py +0 -0
  333. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/serve/responses.py +0 -0
  334. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/serve/streaming.py +0 -0
  335. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/serve/thinking.py +0 -0
  336. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/serve/urls.py +0 -0
  337. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/server/__init__.py +0 -0
  338. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/server/__main__.py +0 -0
  339. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/server/app.py +0 -0
  340. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/server/billing/__init__.py +0 -0
  341. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/server/billing/charges.py +0 -0
  342. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/server/billing/retry.py +0 -0
  343. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/server/domain/__init__.py +0 -0
  344. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/server/domain/checkpoints.py +0 -0
  345. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/server/domain/environment_registry.py +0 -0
  346. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/server/domain/envs.py +0 -0
  347. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/server/domain/projects.py +0 -0
  348. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/server/domain/reconcile.py +0 -0
  349. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/server/domain/repo_cleanup.py +0 -0
  350. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/server/domain/run_registry.py +0 -0
  351. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/server/domain/teacher_broker.py +0 -0
  352. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/server/domain/teacher_errors.py +0 -0
  353. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/server/domain/teacher_requests.py +0 -0
  354. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/server/platform/__init__.py +0 -0
  355. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/server/platform/auth.py +0 -0
  356. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/server/platform/db.py +0 -0
  357. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/server/platform/deps.py +0 -0
  358. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/server/platform/internal_client.py +0 -0
  359. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/server/platform/locks.py +0 -0
  360. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/server/platform/runtime.py +0 -0
  361. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/server/routes/__init__.py +0 -0
  362. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/server/routes/envs.py +0 -0
  363. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/server/routes/meta.py +0 -0
  364. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/server/routes/runs.py +0 -0
  365. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/server/routes/serving.py +0 -0
  366. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/server/routes/serving_completion.py +0 -0
  367. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/server/routes/serving_revisions.py +0 -0
  368. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/server/routes/serving_smoke.py +0 -0
  369. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/server/routes/teacher.py +0 -0
  370. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/teacher/__init__.py +0 -0
  371. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/teacher/limits.py +0 -0
  372. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/flash/teacher/retry_contract.py +0 -0
  373. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/scripts/build_dev_dist.py +0 -0
  374. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/scripts/check_file_size.py +0 -0
  375. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/scripts/check_function_size.py +0 -0
  376. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/scripts/check_verl_pin_exists.py +0 -0
  377. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/scripts/scrub_history.sh +0 -0
  378. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/__init__.py +0 -0
  379. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/_helpers/__init__.py +0 -0
  380. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/_helpers/profile.py +0 -0
  381. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/_helpers/runner.py +0 -0
  382. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/_helpers/specs.py +0 -0
  383. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/_helpers/teacher.py +0 -0
  384. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/_helpers/vast.py +0 -0
  385. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/capture_image_sft_processor_oracle.py +0 -0
  386. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/conftest.py +0 -0
  387. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/fixtures/image_sft_processor_oracle.json +0 -0
  388. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/fixtures/math_eval.jsonl +0 -0
  389. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/fixtures/math_train.jsonl +0 -0
  390. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/live/__init__.py +0 -0
  391. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/live/conftest.py +0 -0
  392. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/live/test_lambda_live.py +0 -0
  393. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/live/test_runpod_live.py +0 -0
  394. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/live/test_sft_thinking_render_live.py +0 -0
  395. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/live/test_vast_live.py +0 -0
  396. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_accounting_coverage.py +0 -0
  397. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_adapter_shard_completeness.py +0 -0
  398. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_agent_flash_cli_contract.py +0 -0
  399. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_algorithms.py +0 -0
  400. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_allocator.py +0 -0
  401. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_backend_jobspec_contract.py +0 -0
  402. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_bake_kernel_cache.py +0 -0
  403. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_base_model_provenance.py +0 -0
  404. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_billing_retry.py +0 -0
  405. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_build_context_contract.py +0 -0
  406. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_cancel_remote.py +0 -0
  407. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_catalog_consistency.py +0 -0
  408. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_catalog_only_models.py +0 -0
  409. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_charge_pricing.py +0 -0
  410. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_checkpoint_lifecycle.py +0 -0
  411. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_checkpoints.py +0 -0
  412. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_cli_commands.py +0 -0
  413. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_cli_commands_coverage.py +0 -0
  414. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_cli_credential_shadowing.py +0 -0
  415. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_cli_errors.py +0 -0
  416. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_cli_estimate.py +0 -0
  417. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_cli_gpus_flag.py +0 -0
  418. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_cli_help.py +0 -0
  419. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_cli_main_coverage.py +0 -0
  420. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_cli_managed.py +0 -0
  421. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_cli_render_coverage.py +0 -0
  422. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_cli_render_theme.py +0 -0
  423. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_cli_traces.py +0 -0
  424. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_cli_wandb_warning.py +0 -0
  425. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_client.py +0 -0
  426. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_client_import_purity.py +0 -0
  427. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_client_server_integration.py +0 -0
  428. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_client_stream_reads.py +0 -0
  429. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_config_env_vars.py +0 -0
  430. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_config_overrides.py +0 -0
  431. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_console_upload.py +0 -0
  432. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_controlled_experiment_repairs.py +0 -0
  433. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_cost_analytical.py +0 -0
  434. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_cost_equation.py +0 -0
  435. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_cost_estimate.py +0 -0
  436. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_cost_hardware.py +0 -0
  437. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_cost_models.py +0 -0
  438. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_dataset_profile.py +0 -0
  439. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_deploy_alias_move_warning.py +0 -0
  440. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_deploy_latency.py +0 -0
  441. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_dev_channel.py +0 -0
  442. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_disk_gb.py +0 -0
  443. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_endpoint_name.py +0 -0
  444. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_env_cache_evict.py +0 -0
  445. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_env_delete.py +0 -0
  446. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_env_download.py +0 -0
  447. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_env_download_api.py +0 -0
  448. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_env_evaluations.py +0 -0
  449. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_env_list_api.py +0 -0
  450. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_env_list_cli.py +0 -0
  451. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_env_list_hub.py +0 -0
  452. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_env_no_install.py +0 -0
  453. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_env_publish.py +0 -0
  454. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_env_pull.py +0 -0
  455. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_env_pull_coverage.py +0 -0
  456. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_env_pull_loader_coverage.py +0 -0
  457. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_env_pull_managed_control_plane.py +0 -0
  458. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_env_push.py +0 -0
  459. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_env_rate_limit_resolve.py +0 -0
  460. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_env_ref_pinning.py +0 -0
  461. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_env_test.py +0 -0
  462. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_export.py +0 -0
  463. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_flash_mvp.py +0 -0
  464. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_flashinfer_cache_dirs.py +0 -0
  465. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_freesolo_api_transport.py +0 -0
  466. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_fused_expert_warmstart.py +0 -0
  467. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_github_urlopen_retry.py +0 -0
  468. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_gpu_type_single_field.py +0 -0
  469. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_gpus.py +0 -0
  470. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_grpo_params.py +0 -0
  471. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_grpo_resident_sizing.py +0 -0
  472. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_grpo_reward_batching.py +0 -0
  473. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_health_liveness.py +0 -0
  474. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_hf_retry.py +0 -0
  475. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_idle_endpoint_reaper.py +0 -0
  476. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_image_sft_markers.py +0 -0
  477. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_image_sft_processor_parity.py +0 -0
  478. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_image_tokens.py +0 -0
  479. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_infisical_secrets.py +0 -0
  480. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_internal_client.py +0 -0
  481. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_jobs.py +0 -0
  482. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_kernel_cache.py +0 -0
  483. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_kernel_fingerprint.py +0 -0
  484. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_kv_util.py +0 -0
  485. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_lambda_api_coverage.py +0 -0
  486. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_lambda_runner.py +0 -0
  487. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_logging.py +0 -0
  488. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_login_perms.py +0 -0
  489. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_lora_rank_coverage.py +0 -0
  490. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_lora_rank_preflight.py +0 -0
  491. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_managed_config_fields.py +0 -0
  492. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_managed_hf_repo.py +0 -0
  493. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_metrics_schema_agent_contract.py +0 -0
  494. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_mig_guard.py +0 -0
  495. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_multi_gpu_gate.py +0 -0
  496. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_multimodal_training.py +0 -0
  497. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_named_reward_metrics.py +0 -0
  498. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_oom_escalate_gpu.py +0 -0
  499. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_opd.py +0 -0
  500. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_opd_limits.py +0 -0
  501. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_opd_multiturn_eos_boundary.py +0 -0
  502. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_opd_multiturn_failure_exit.py +0 -0
  503. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_opd_replay_guard.py +0 -0
  504. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_orchestrator_flash.py +0 -0
  505. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_packing.py +0 -0
  506. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_packing_coverage.py +0 -0
  507. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_parasail_teacher.py +0 -0
  508. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_persisted_spec_envelope.py +0 -0
  509. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_poll_helpers.py +0 -0
  510. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_preflight.py +0 -0
  511. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_projects.py +0 -0
  512. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_prompt_budget.py +0 -0
  513. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_provider_preflight_coverage.py +0 -0
  514. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_provider_routing.py +0 -0
  515. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_provider_teardown_robustness.py +0 -0
  516. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_providers_symmetry.py +0 -0
  517. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_realized_cost.py +0 -0
  518. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_repo_cleanup.py +0 -0
  519. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_resolve_params_b.py +0 -0
  520. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_resume_on_retry.py +0 -0
  521. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_rollout_samples.py +0 -0
  522. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_runmgmt.py +0 -0
  523. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_runpod_api_delete.py +0 -0
  524. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_runpod_key_fingerprint.py +0 -0
  525. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_runpod_key_waterfall.py +0 -0
  526. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_runtime_capsule.py +0 -0
  527. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_serve.py +0 -0
  528. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_serve_reasoning_content.py +0 -0
  529. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_server_api.py +0 -0
  530. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_server_app_coverage.py +0 -0
  531. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_server_auth_singleflight.py +0 -0
  532. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_server_billing.py +0 -0
  533. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_server_checkpoints_coverage.py +0 -0
  534. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_server_db.py +0 -0
  535. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_server_envs_coverage.py +0 -0
  536. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_server_locks_coverage.py +0 -0
  537. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_server_standalone.py +0 -0
  538. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_serving_context_preflight.py +0 -0
  539. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_serving_contract.py +0 -0
  540. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_serving_schema_coverage.py +0 -0
  541. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_sft_chunked_nll.py +0 -0
  542. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_sft_example_selection.py +0 -0
  543. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_sft_gc_off.py +0 -0
  544. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_sft_max_context.py +0 -0
  545. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_sft_startup_block.py +0 -0
  546. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_sft_workload.py +0 -0
  547. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_spec_and_validation.py +0 -0
  548. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_spec_contract_bytes.py +0 -0
  549. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_step_floor.py +0 -0
  550. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_step_metrics.py +0 -0
  551. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_step_timing.py +0 -0
  552. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_structured_outputs.py +0 -0
  553. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_teacher_broker.py +0 -0
  554. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_teacher_encoding_contract.py +0 -0
  555. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_terminal_artifacts.py +0 -0
  556. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_thinking_config.py +0 -0
  557. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_train_context_preflight.py +0 -0
  558. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_training_controls.py +0 -0
  559. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_type_comment_prose.py +0 -0
  560. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_vast_api.py +0 -0
  561. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_vast_api_coverage.py +0 -0
  562. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_vast_offers.py +0 -0
  563. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_vast_provider_coverage.py +0 -0
  564. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_vast_runner.py +0 -0
  565. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_verified_revisions.py +0 -0
  566. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_verifiers.py +0 -0
  567. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_verl_checkpoint_export.py +0 -0
  568. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_verl_child_plugins.py +0 -0
  569. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_verl_silence_watchdog.py +0 -0
  570. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_version.py +0 -0
  571. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_vl_warmstart_adapter_keys.py +0 -0
  572. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_vram_architecture.py +0 -0
  573. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_wandb_link.py +0 -0
  574. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_wandb_naming.py +0 -0
  575. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_warmstart_adapter_download.py +0 -0
  576. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_warmstart_cross_repo.py +0 -0
  577. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_warmstart_error_attribution.py +0 -0
  578. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_weight_cache.py +0 -0
  579. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_worker_dryrun.py +0 -0
  580. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_worker_hardexit.py +0 -0
  581. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_worker_image.py +0 -0
  582. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_worker_init_heartbeat.py +0 -0
  583. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_worker_stack.py +0 -0
  584. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_worker_thinking.py +0 -0
  585. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_workflow_contracts.py +0 -0
  586. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/tests/test_workload_profile.py +0 -0
  587. {freesolo_flash_dev-1.2.65 → freesolo_flash_dev-1.2.67}/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.65
3
+ Version: 1.2.67
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
+ )
@@ -14,6 +14,7 @@ import sys
14
14
  import threading
15
15
  import time
16
16
 
17
+ from flash._internal.diagnostics import SECRET_ENV_KEYS_ENV
17
18
  from flash.adapters.lora_rank import rank_from_adapter_config
18
19
  from flash.engine.worker.runtime.pkg_proxy import W as _w
19
20
  from flash.engine.worker.verl.checkpoints import resume_checkpoint_is_loadable
@@ -203,6 +204,9 @@ _CHILD_ENV_PREFIXES = (
203
204
 
204
205
 
205
206
  def _build_verl_child_env(*, shim_dir: str, wandb_enabled: bool) -> dict[str, str]:
207
+ applied_secret_names = frozenset(
208
+ name.strip() for name in os.environ.get(SECRET_ENV_KEYS_ENV, "").split(",") if name.strip()
209
+ )
206
210
  child = {
207
211
  key: value
208
212
  for key, value in os.environ.items()
@@ -210,9 +214,16 @@ def _build_verl_child_env(*, shim_dir: str, wandb_enabled: bool) -> dict[str, st
210
214
  }
211
215
  if wandb_enabled:
212
216
  child.update({key: value for key, value in os.environ.items() if key.startswith("WANDB_")})
213
- child["PYTHONPATH"] = os.pathsep.join(
214
- item for item in (shim_dir, os.environ.get("PYTHONPATH", "")) if item
217
+ # retained runtime namespaces are filtered by applied-secret provenance. authenticated child-side
218
+ # wandb logging is the sole secret exception, and only when the existing logger gate enables it.
219
+ for name in applied_secret_names:
220
+ child.pop(name, None)
221
+ if wandb_enabled and "WANDB_API_KEY" in os.environ:
222
+ child["WANDB_API_KEY"] = os.environ["WANDB_API_KEY"]
223
+ parent_pythonpath = (
224
+ os.environ.get("PYTHONPATH", "") if "PYTHONPATH" not in applied_secret_names else ""
215
225
  )
226
+ child["PYTHONPATH"] = os.pathsep.join(item for item in (shim_dir, parent_pythonpath) if item)
216
227
  child["PYTHONUNBUFFERED"] = "1"
217
228
  child["HYDRA_FULL_ERROR"] = "1"
218
229
  child["HF_HUB_OFFLINE"] = "1"
@@ -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
 
@@ -62,31 +62,49 @@ def _train_body(input_data: dict) -> dict:
62
62
 
63
63
  from huggingface_hub import snapshot_download
64
64
 
65
+ def _percent_pattern(needle):
66
+ """Regex matching only percent-escape hex digits case-insensitively."""
67
+ escape_re = re.compile(r"%([0-9A-Fa-f]{2})")
68
+ parts = []
69
+ offset = 0
70
+ for match in escape_re.finditer(needle):
71
+ parts.append(re.escape(needle[offset : match.start()]))
72
+ parts.append("%")
73
+ parts.extend(
74
+ f"[{char.lower()}{char.upper()}]" if char.isalpha() else char
75
+ for char in match.group(1)
76
+ )
77
+ offset = match.end()
78
+ parts.append(re.escape(needle[offset:]))
79
+ return "".join(parts)
80
+
65
81
  def _needles(secrets=None):
66
- """The (plain, bounded) credential needle sets for os.environ plus ``secrets``.
67
-
68
- a value at or above the floor is a plain needle, replaced as a substring; a SHORTER one is
69
- bounded, matched only where it is not adjacent to a word character. short values used to be
70
- dropped outright, which leaked them verbatim -- [environment] secrets accepts any name and
71
- any value. plain replacement is not the alternative: a 3-char needle corrupts every
72
- diagnostic that merely contains those letters (the value "ati" rewrites "authentication").
73
-
74
- a multiline secret (a PEM key) never appears whole in any single call: the child's stdout is
75
- sanitized one line at a time, so only a component line is ever seen. component lines keep
76
- the floor as a hard skip -- a short one is punctuation such as "}", not a credential.
77
- Mirrors flash.providers._lifecycle.bootstrap_secrets._needles.
82
+ """Typed value matchers, shape-only needles, and raw values for all known secrets.
83
+
84
+ each value matcher carries ``(needle, bounded, encoded)`` metadata. a value at or above the
85
+ floor is plain and replaced as a substring; a shorter one is bounded, matched only where it is
86
+ not adjacent to a word character. short values used to be dropped outright, which leaked them
87
+ verbatim. plain replacement is not the alternative: a 3-char needle corrupts every diagnostic
88
+ that merely contains those letters (the value "ati" rewrites "authentication"). a short raw
89
+ candidate with no alphanumeric or underscore character is shape-only because it is
90
+ indistinguishable from ordinary punctuation. explicit percent-octet forms remain bounded.
91
+
92
+ a multiline secret never appears whole in any single call: the child's stdout is sanitized one
93
+ line at a time, so only a component line is ever seen. component lines keep the floor as a hard
94
+ skip: a short one is punctuation such as "}", not a credential. mirrors
95
+ flash.providers._lifecycle.bootstrap_secrets._needles.
78
96
  """
79
97
  import urllib.parse
80
98
 
81
99
  mapping = {**os.environ, **(secrets or {})}
82
100
  # declared runtime secrets can carry any name, so the control plane lists them in
83
- # FLASH_SECRET_ENV_KEYS; the name-shape rule stays as the fail-closed fallback.
101
+ # flash_secret_env_keys; the name-shape rule stays as the fail-closed fallback.
84
102
  declared = {
85
103
  name.strip().upper()
86
104
  for name in str(mapping.get("FLASH_SECRET_ENV_KEYS") or "").split(",")
87
105
  if name.strip()
88
106
  }
89
- plain, bounded = set(), set()
107
+ matchers, shaped, raw_values = set(), set(), set()
90
108
  for key, secret in mapping.items():
91
109
  upper = str(key).upper()
92
110
  if not secret or not (
@@ -96,34 +114,78 @@ def _train_body(input_data: dict) -> dict:
96
114
  ):
97
115
  continue
98
116
  value_str = str(secret)
99
- target = plain if len(value_str) >= 8 else bounded
100
- target.update({value_str, urllib.parse.quote(value_str, safe="")})
117
+ raw_values.add(value_str)
118
+ candidates = {(value_str, False)}
119
+ encoded = urllib.parse.quote(value_str, safe="")
120
+ if encoded != value_str:
121
+ candidates.add((encoded, True))
122
+ if len(value_str) < 8 and not any(char.isalnum() or char == "_" for char in value_str):
123
+ candidates.add(("".join(f"%{byte:02X}" for byte in value_str.encode()), True))
124
+ if len(value_str) >= 8:
125
+ matchers.update(
126
+ (candidate, False, is_encoded) for candidate, is_encoded in candidates
127
+ )
128
+ else:
129
+ for candidate, is_encoded in candidates:
130
+ if any(char.isalnum() or char == "_" for char in candidate):
131
+ matchers.add((candidate, True, is_encoded))
132
+ else:
133
+ shaped.add(candidate)
101
134
  if "\n" in value_str:
102
135
  for raw in value_str.splitlines():
103
136
  if len(line := raw.strip()) >= 8:
104
- plain.update({line, urllib.parse.quote(line, safe="")})
105
- return plain, bounded
137
+ matchers.add((line, False, False))
138
+ encoded_line = urllib.parse.quote(line, safe="")
139
+ if encoded_line != line:
140
+ matchers.add((encoded_line, False, True))
141
+ return matchers, shaped, raw_values
106
142
 
107
143
  def _safe_detail(value, secrets=None, limit=1000):
108
144
  text = (
109
145
  f"{type(value).__name__}: {value}" if isinstance(value, BaseException) else str(value)
110
146
  )
111
- plain, bounded = _needles(secrets)
112
- # longest-first so one secret containing another cannot leave a suffix of the longer
113
- # one behind; encoded forms cover the percent-encoded urls http and git errors print.
114
- for needle in sorted(plain, key=len, reverse=True):
115
- text = text.replace(needle, "<redacted>")
116
- for needle in sorted(bounded, key=len, reverse=True):
117
- # the word guard is applied per EDGE, and only where the needle's own edge is a word
118
- # character. a value with a punctuation edge already separates itself from neighbouring
119
- # text, and demanding a non-word character beyond it asks the wrong question: "/a"
120
- # inside "https://host/a/repo" is preceded by the "t" of "host", so an unconditional
121
- # left guard fails and the secret prints verbatim. "ati" keeps both guards and so still
122
- # cannot rewrite "authentication".
123
- # Mirrors flash.providers._lifecycle.bootstrap_secrets._bounded_pattern.
124
- left = r"(?<!\w)" if needle[:1].isalnum() or needle[:1] == "_" else ""
125
- right = r"(?!\w)" if needle[-1:].isalnum() or needle[-1:] == "_" else ""
126
- text = re.sub(f"{left}{re.escape(needle)}{right}", "<redacted>", text)
147
+ matchers, shaped, raw_values = _needles(secrets)
148
+ # protect exact punctuation credentials before a separate value can erase their syntax.
149
+ for needle in sorted(shaped, key=len, reverse=True):
150
+ escaped = re.escape(needle)
151
+ text = re.sub(
152
+ rf"(?i)(authorization|api[-_ ]?key|access[-_ ]?token|token|secret|password)(\s*[:=]\s*)(?:bearer\s+)?{escaped}(?=[\s,;]|$)",
153
+ lambda match: (
154
+ "<redacted>"
155
+ if match.group(1) in raw_values
156
+ else f"{match.group(1)}{match.group(2)}<redacted>"
157
+ ),
158
+ text,
159
+ )
160
+ text = re.sub(
161
+ rf"(?i)\b(bearer)\s+{escaped}(?=[\s,;]|$)",
162
+ lambda match: "<redacted>" if match.group(1) in raw_values else "Bearer <redacted>",
163
+ text,
164
+ )
165
+ # longest-first across both matcher types so a shorter plain value cannot consume the prefix
166
+ # of a longer bounded encoded value; encoded forms cover urls http and git errors print.
167
+ for needle, is_bounded, is_encoded in sorted(
168
+ matchers, key=lambda item: len(item[0]), reverse=True
169
+ ):
170
+ if is_encoded:
171
+ pattern = _percent_pattern(needle)
172
+ if is_bounded:
173
+ left = r"(?<!\w)" if needle[:1].isalnum() or needle[:1] == "_" else ""
174
+ right = r"(?!\w)" if needle[-1:].isalnum() or needle[-1:] == "_" else ""
175
+ pattern = f"{left}{pattern}{right}"
176
+ text = re.sub(pattern, "<redacted>", text)
177
+ elif is_bounded:
178
+ # the word guard is applied per edge, and only where the needle's own edge is a word
179
+ # character. a value with a punctuation edge already separates itself from
180
+ # neighbouring text, and demanding a non-word character beyond it asks the wrong
181
+ # question: "/a" inside "https://host/a/repo" is preceded by the "t" of "host", so
182
+ # an unconditional left guard fails and the secret prints verbatim. "ati" keeps both
183
+ # guards and so still cannot rewrite "authentication".
184
+ left = r"(?<!\w)" if needle[:1].isalnum() or needle[:1] == "_" else ""
185
+ right = r"(?!\w)" if needle[-1:].isalnum() or needle[-1:] == "_" else ""
186
+ text = re.sub(f"{left}{re.escape(needle)}{right}", "<redacted>", text)
187
+ else:
188
+ text = text.replace(needle, "<redacted>")
127
189
  text = re.sub(r"(?i)\bbearer\s+[A-Za-z0-9._~+/=-]+", "Bearer <redacted>", text)
128
190
  text = re.sub(
129
191
  r"(?i)(authorization|api[-_ ]?key|access[-_ ]?token|token|secret|password)"
@@ -475,13 +475,13 @@ def _pinned_to_resume_width(allocation, resume_world_size: int | None):
475
475
  the one the attempt runs at: it refuses to train rather than restart from step 0, because the
476
476
  control-plane gate authorized this replacement only to continue from exactly that checkpoint.
477
477
  Allocation, though, re-ranks every retry from scratch -- capacity and live pricing move, and
478
- 2x/4x of a class are distinct rentable shapes -- so a 2-card attempt can legitimately be
479
- re-ranked onto 4 cards and then permanently reject the only checkpoint it may resume from.
478
+ rentable shapes can carry more cards than the ranks that join the run. Comparing the checkpoint
479
+ width with the rented count can reject a loadable shape or admit one the worker cannot load.
480
480
 
481
- Narrowing the candidates is what closes that gap, and it is done HERE rather than by passing a
481
+ Narrowing the candidates is what closes that gap, and it is done here rather than by passing a
482
482
  count into ``allocate()``: ``max_gpu_count`` is a ceiling, not an exact width, so a ceiling of 2
483
- still admits a 1-card shape. Every candidate already carries its own ``gpu_count``, so the
484
- exact-width rule is one filter over the ranked list, leaving the ranking itself untouched.
483
+ still admits a 1-card shape. Allocator-stamped candidates carry their executed rank count while
484
+ unstamped candidates fall back to their rented count. The filter leaves ranking and shapes intact.
485
485
 
486
486
  An empty result is left empty deliberately: the caller reports no-capacity and retries, which is
487
487
  the truthful outcome when the only loadable shape is unavailable. Restarting from step 0 instead
@@ -489,11 +489,17 @@ def _pinned_to_resume_width(allocation, resume_world_size: int | None):
489
489
  """
490
490
  if not resume_world_size:
491
491
  return allocation
492
- loadable = tuple(
493
- candidate
494
- for candidate in allocation.candidates
495
- if int(getattr(candidate, "gpu_count", 1)) == resume_world_size
496
- )
492
+ loadable = []
493
+ for candidate in allocation.candidates:
494
+ executed_gpu_count = getattr(candidate, "executed_gpu_count", None)
495
+ width = (
496
+ executed_gpu_count
497
+ if type(executed_gpu_count) is int and executed_gpu_count > 0
498
+ else int(getattr(candidate, "gpu_count", 1))
499
+ )
500
+ if width == resume_world_size:
501
+ loadable.append(candidate)
502
+ loadable = tuple(loadable)
497
503
  if loadable == allocation.candidates:
498
504
  return allocation
499
505
  if not loadable:
@@ -520,16 +526,16 @@ def _build_candidate_plan(
520
526
  if not candidates:
521
527
  # an exhausted list has two causes and they need different words. attributing the pinned-
522
528
  # width one to OOM would send an operator to raise VRAM when the run is not out of memory
523
- # at all: no fitting shape has the card count its resume checkpoint can be loaded on.
529
+ # at all: no fitting candidate executes at the resume checkpoint's world size.
524
530
  if prepared.resume_world_size and not allocation.candidates:
525
531
  width = prepared.resume_world_size
526
532
  ctx.last_detail = (
527
- f"no fitting {width}-card shape is available, and this retry must resume from a "
528
- f"checkpoint written at {width} cards"
533
+ f"no candidate executing at checkpoint world size {width} is available, and this "
534
+ "retry must preserve that executed rank width"
529
535
  )
530
536
  print(
531
- f"seed={ctx.seed} no {width}-card candidate for the pinned OPD resume checkpoint; "
532
- "not retrying",
537
+ f"seed={ctx.seed} no candidate executes at pinned OPD checkpoint world size "
538
+ f"{width}; not retrying",
533
539
  file=ctx.log,
534
540
  flush=True,
535
541
  )
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "freesolo-flash-dev"
3
- version = "1.2.65"
3
+ version = "1.2.67"
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.65"
140
+ version = "1.2.67"
141
141
 
142
142
  [tool.pytest.ini_options]
143
143
  pythonpath = ["."]