freesolo-flash-dev 1.2.33__tar.gz → 1.2.36__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 (538) hide show
  1. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/PKG-INFO +1 -1
  2. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/cli/__init__.py +2 -2
  3. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/cli/commands/env/episode.py +72 -30
  4. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/cli/commands/env/eval.py +7 -4
  5. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/cli/commands/env/setup.py +9 -7
  6. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/cli/commands/env/test.py +26 -20
  7. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/cli/commands/env/test_evaluations.py +58 -4
  8. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/cli/scaffold/TRAINING.md +5 -0
  9. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/envs/evaluations.py +41 -7
  10. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/runner/supervise/transitions.py +24 -3
  11. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/serve/deploy.py +17 -9
  12. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/serve/errors.py +16 -0
  13. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/server/routes/serving.py +3 -3
  14. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/server/routes/serving_completion.py +133 -59
  15. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/server/routes/serving_revisions.py +38 -7
  16. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/server/routes/serving_smoke.py +109 -29
  17. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/pyproject.toml +2 -2
  18. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_cli_commands.py +6 -0
  19. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_env_evaluations.py +92 -14
  20. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_env_test.py +370 -23
  21. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_serve.py +11 -8
  22. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_server_api.py +624 -47
  23. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_server_envs_coverage.py +310 -5
  24. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/uv.lock +1 -1
  25. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/.dockerignore +0 -0
  26. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/.env.example +0 -0
  27. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/.github/CODEOWNERS +0 -0
  28. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  29. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  30. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  31. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  32. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/.github/dependabot.yml +0 -0
  33. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/.github/workflows/auto-rebake.yml +0 -0
  34. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/.github/workflows/bake-kernel-cache.yml +0 -0
  35. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/.github/workflows/ci.yml +0 -0
  36. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/.github/workflows/main-source-guard.yml +0 -0
  37. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/.github/workflows/notify-tests-repo.yml +0 -0
  38. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/.github/workflows/publish-dev.yml +0 -0
  39. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/.github/workflows/publish-image.yml +0 -0
  40. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/.github/workflows/publish.yml +0 -0
  41. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/.github/workflows/version-parity.yml +0 -0
  42. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/.github/workflows/worker-image.yml +0 -0
  43. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/.gitignore +0 -0
  44. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/CHANGELOG.md +0 -0
  45. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/CODE_OF_CONDUCT.md +0 -0
  46. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/CONTRIBUTING.md +0 -0
  47. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/Dockerfile +0 -0
  48. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/Dockerfile.worker +0 -0
  49. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/LICENSE +0 -0
  50. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/NOTICE +0 -0
  51. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/README.md +0 -0
  52. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/SECURITY.md +0 -0
  53. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/SELF_HOSTING.md +0 -0
  54. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/build/kernel_cache/.gitignore +0 -0
  55. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/build/kernel_cache/.keep +0 -0
  56. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/deploy/infisical/README.md +0 -0
  57. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/deploy/infisical/entrypoint.sh +0 -0
  58. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/docker/Dockerfile.kernelcache +0 -0
  59. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/docker/Dockerfile.kernelcache.relayer +0 -0
  60. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/docker/bake_kernel_cache.py +0 -0
  61. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/docker/bake_pod_entry.py +0 -0
  62. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/docker/extract_cudart_fix.py +0 -0
  63. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/docker/kernel_fingerprint.py +0 -0
  64. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/docker/make_rp_handler.py +0 -0
  65. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/__init__.py +0 -0
  66. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/_internal/__init__.py +0 -0
  67. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/_internal/channel.py +0 -0
  68. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/_internal/diagnostics.py +0 -0
  69. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/_internal/fileio.py +0 -0
  70. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/_internal/logging.py +0 -0
  71. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/_internal/paths.py +0 -0
  72. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/adapters/__init__.py +0 -0
  73. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/adapters/artifacts.py +0 -0
  74. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/adapters/lora_rank.py +0 -0
  75. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/cli/__main__.py +0 -0
  76. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/cli/commands/__init__.py +0 -0
  77. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/cli/commands/deploy.py +0 -0
  78. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/cli/commands/env/__init__.py +0 -0
  79. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/cli/commands/env/eval_args.py +0 -0
  80. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/cli/commands/env/imports.py +0 -0
  81. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/cli/commands/env/list.py +0 -0
  82. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/cli/commands/env/push.py +0 -0
  83. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/cli/commands/env/retained.py +0 -0
  84. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/cli/commands/env/test_params.py +0 -0
  85. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/cli/commands/env/test_warnings.py +0 -0
  86. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/cli/commands/traces.py +0 -0
  87. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/cli/commands/train_cost.py +0 -0
  88. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/cli/scaffold/__init__.py +0 -0
  89. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/cli/ui/__init__.py +0 -0
  90. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/cli/ui/cost.py +0 -0
  91. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/cli/ui/env_panels.py +0 -0
  92. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/cli/ui/heartbeat.py +0 -0
  93. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/cli/ui/render.py +0 -0
  94. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/cli/ui/tables.py +0 -0
  95. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/cli/ui/tty.py +0 -0
  96. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/client/__init__.py +0 -0
  97. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/client/config.py +0 -0
  98. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/client/freesolo_api.py +0 -0
  99. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/client/http.py +0 -0
  100. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/client/runtime_secrets.py +0 -0
  101. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/client/shapes.py +0 -0
  102. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/client/specs.py +0 -0
  103. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/client/streaming.py +0 -0
  104. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/content/__init__.py +0 -0
  105. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/content/multimodal.py +0 -0
  106. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/content/structured_outputs.py +0 -0
  107. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/content/thinking.py +0 -0
  108. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/core/__init__.py +0 -0
  109. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/core/catalog.py +0 -0
  110. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/core/spec.py +0 -0
  111. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/cost/__init__.py +0 -0
  112. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/cost/analytical.py +0 -0
  113. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/cost/facts.py +0 -0
  114. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/cost/spec.py +0 -0
  115. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/cost/types.py +0 -0
  116. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/__init__.py +0 -0
  117. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/plan/__init__.py +0 -0
  118. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/plan/kv_sizing.py +0 -0
  119. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/plan/model_config_probe.py +0 -0
  120. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/plan/recipe.py +0 -0
  121. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/plan/steps.py +0 -0
  122. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/plan/vram.py +0 -0
  123. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/profiling/__init__.py +0 -0
  124. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/profiling/dataset_profile.py +0 -0
  125. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/profiling/reasoning_render.py +0 -0
  126. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/profiling/sft_workload.py +0 -0
  127. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/profiling/tokenizer.py +0 -0
  128. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/profiling/workload_profile.py +0 -0
  129. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/result/__init__.py +0 -0
  130. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/result/accounting.py +0 -0
  131. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/result/rollout_samples.py +0 -0
  132. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/__init__.py +0 -0
  133. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/__main__.py +0 -0
  134. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/backend_common.py +0 -0
  135. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/entry/__init__.py +0 -0
  136. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/entry/opd.py +0 -0
  137. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/entry/rl.py +0 -0
  138. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/entry/sft.py +0 -0
  139. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/io/__init__.py +0 -0
  140. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/io/heartbeat.py +0 -0
  141. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/io/hf.py +0 -0
  142. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/io/prefetch.py +0 -0
  143. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/io/wandb_log.py +0 -0
  144. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/model/__init__.py +0 -0
  145. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/model/adapter.py +0 -0
  146. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/model/decoding.py +0 -0
  147. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/model/lora.py +0 -0
  148. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/model/packing.py +0 -0
  149. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/opd_train.py +0 -0
  150. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/opd_train_runner.py +0 -0
  151. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/perf/__init__.py +0 -0
  152. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/perf/diagnostics.py +0 -0
  153. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/perf/lifecycle.py +0 -0
  154. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/perf/liger.py +0 -0
  155. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/perf/memory.py +0 -0
  156. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/rl_train.py +0 -0
  157. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/rl_train_runner.py +0 -0
  158. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/runtime/__init__.py +0 -0
  159. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/runtime/kernel_warmup.py +0 -0
  160. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/runtime/pkg_proxy.py +0 -0
  161. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/runtime/rng.py +0 -0
  162. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/score_batcher.py +0 -0
  163. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/sft_train.py +0 -0
  164. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/sft_train_runner.py +0 -0
  165. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/teacher/__init__.py +0 -0
  166. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/teacher/client.py +0 -0
  167. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/teacher/encoding.py +0 -0
  168. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/teacher/tokenizer_align.py +0 -0
  169. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/train/__init__.py +0 -0
  170. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/train/core/__init__.py +0 -0
  171. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/train/core/child/__init__.py +0 -0
  172. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/train/core/child/glue.py +0 -0
  173. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/train/core/step_timing.py +0 -0
  174. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/train/finalize.py +0 -0
  175. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/train/opd/__init__.py +0 -0
  176. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/train/opd/batching.py +0 -0
  177. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/train/opd/bridge.py +0 -0
  178. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/train/opd/child/__init__.py +0 -0
  179. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/train/opd/child/bridge.py +0 -0
  180. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/train/opd/child/multiturn.py +0 -0
  181. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/train/opd/child/plugin.py +0 -0
  182. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/train/opd/child/structured.py +0 -0
  183. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/train/opd/failures.py +0 -0
  184. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/train/opd/gkd.py +0 -0
  185. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/train/opd/multiturn_validation.py +0 -0
  186. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/train/opd/overrides.py +0 -0
  187. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/train/opd/prompts.py +0 -0
  188. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/train/opd/reporting.py +0 -0
  189. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/train/opd/scoring.py +0 -0
  190. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/train/opd/state.py +0 -0
  191. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/train/opd/validation.py +0 -0
  192. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/train/rl/__init__.py +0 -0
  193. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/train/rl/checkpoints.py +0 -0
  194. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/train/rl/child/__init__.py +0 -0
  195. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/train/rl/child/multiturn.py +0 -0
  196. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/train/rl/child/plugin.py +0 -0
  197. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/train/rl/config.py +0 -0
  198. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/train/rl/inputs.py +0 -0
  199. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/train/rl/multi_turn.py +0 -0
  200. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/train/rl/scoring.py +0 -0
  201. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/train/rl/shims.py +0 -0
  202. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/train/rl/single_turn.py +0 -0
  203. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/train/rl/verl_config.py +0 -0
  204. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/train/sft/__init__.py +0 -0
  205. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/train/sft/checkpoints.py +0 -0
  206. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/train/sft/config.py +0 -0
  207. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/verl/__init__.py +0 -0
  208. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/verl/capabilities.py +0 -0
  209. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/verl/checkpoints.py +0 -0
  210. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/verl/child_io.py +0 -0
  211. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/verl/diagnostics.py +0 -0
  212. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker/verl/parallelism.py +0 -0
  213. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/engine/worker_entrypoint.py +0 -0
  214. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/envs/__init__.py +0 -0
  215. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/envs/adapter.py +0 -0
  216. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/envs/base.py +0 -0
  217. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/envs/cache_security.py +0 -0
  218. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/envs/dataset_selection.py +0 -0
  219. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/envs/identity.py +0 -0
  220. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/envs/loader.py +0 -0
  221. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/envs/namespace_listing.py +0 -0
  222. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/envs/package/__init__.py +0 -0
  223. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/envs/package/limits.py +0 -0
  224. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/envs/package/unpack.py +0 -0
  225. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/envs/pull.py +0 -0
  226. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/__init__.py +0 -0
  227. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/_lifecycle/__init__.py +0 -0
  228. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/_lifecycle/auth.py +0 -0
  229. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/_lifecycle/bootstrap.py +0 -0
  230. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/_lifecycle/bootstrap_pip.py +0 -0
  231. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/_lifecycle/bootstrap_secrets.py +0 -0
  232. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/_lifecycle/deadline.py +0 -0
  233. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/_lifecycle/http.py +0 -0
  234. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/_lifecycle/instance.py +0 -0
  235. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/_lifecycle/poll.py +0 -0
  236. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/_lifecycle/poll_instance.py +0 -0
  237. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/_lifecycle/provider.py +0 -0
  238. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/_lifecycle/worker.py +0 -0
  239. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/allocator.py +0 -0
  240. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/artifacts/__init__.py +0 -0
  241. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/artifacts/hf.py +0 -0
  242. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/artifacts/preload_runpod.py +0 -0
  243. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/artifacts/weight_cache.py +0 -0
  244. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/base.py +0 -0
  245. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/fit_errors.py +0 -0
  246. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/lambda_/__init__.py +0 -0
  247. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/lambda_/api.py +0 -0
  248. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/lambda_/auth.py +0 -0
  249. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/lambda_/gpus.py +0 -0
  250. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/lambda_/jobs/__init__.py +0 -0
  251. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/lambda_/jobs/builders.py +0 -0
  252. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/lambda_/jobs/reap.py +0 -0
  253. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/lambda_/preflight.py +0 -0
  254. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/lambda_/pricing.py +0 -0
  255. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/preflight.py +0 -0
  256. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/realized.py +0 -0
  257. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/runpod/__init__.py +0 -0
  258. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/runpod/api.py +0 -0
  259. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/runpod/auth.py +0 -0
  260. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/runpod/cost.py +0 -0
  261. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/runpod/gpus.py +0 -0
  262. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/runpod/job_execution.py +0 -0
  263. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/runpod/jobs.py +0 -0
  264. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/runpod/preflight.py +0 -0
  265. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/runpod/pricing.py +0 -0
  266. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/runpod/resources.py +0 -0
  267. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/runpod/serverless/__init__.py +0 -0
  268. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/runpod/serverless/endpoints.py +0 -0
  269. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/sharding.py +0 -0
  270. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/vast/__init__.py +0 -0
  271. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/vast/api.py +0 -0
  272. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/vast/auth.py +0 -0
  273. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/vast/jobs/__init__.py +0 -0
  274. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/vast/jobs/builders.py +0 -0
  275. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/vast/preflight.py +0 -0
  276. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/providers/vast/pricing.py +0 -0
  277. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/py.typed +0 -0
  278. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/runner/__init__.py +0 -0
  279. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/runner/artifacts.py +0 -0
  280. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/runner/attempts.py +0 -0
  281. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/runner/costs.py +0 -0
  282. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/runner/deadlines.py +0 -0
  283. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/runner/preparation.py +0 -0
  284. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/runner/reconciliation.py +0 -0
  285. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/runner/results/__init__.py +0 -0
  286. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/runner/results/checkpoints.py +0 -0
  287. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/runner/results/verified_revisions.py +0 -0
  288. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/runner/status.py +0 -0
  289. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/runner/submit.py +0 -0
  290. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/runner/supervise/__init__.py +0 -0
  291. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/runner/supervise/attach.py +0 -0
  292. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/runner/supervise/deploy.py +0 -0
  293. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/runner/supervise/lifecycle.py +0 -0
  294. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/runner/supervise/recovery.py +0 -0
  295. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/runner/supervise/retry_decision.py +0 -0
  296. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/runner/supervise/seed_submission.py +0 -0
  297. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/runner/weight_cache.py +0 -0
  298. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/schema/__init__.py +0 -0
  299. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/schema/fields.py +0 -0
  300. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/serve/__init__.py +0 -0
  301. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/serve/adapter_check.py +0 -0
  302. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/serve/export.py +0 -0
  303. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/serve/preflight.py +0 -0
  304. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/serve/responses.py +0 -0
  305. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/serve/streaming.py +0 -0
  306. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/serve/thinking.py +0 -0
  307. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/serve/urls.py +0 -0
  308. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/server/__init__.py +0 -0
  309. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/server/__main__.py +0 -0
  310. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/server/app.py +0 -0
  311. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/server/billing/__init__.py +0 -0
  312. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/server/billing/charges.py +0 -0
  313. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/server/billing/retry.py +0 -0
  314. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/server/domain/__init__.py +0 -0
  315. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/server/domain/checkpoints.py +0 -0
  316. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/server/domain/environment_registry.py +0 -0
  317. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/server/domain/envs.py +0 -0
  318. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/server/domain/projects.py +0 -0
  319. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/server/domain/reconcile.py +0 -0
  320. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/server/domain/repo_cleanup.py +0 -0
  321. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/server/domain/run_registry.py +0 -0
  322. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/server/domain/teacher_broker.py +0 -0
  323. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/server/domain/teacher_errors.py +0 -0
  324. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/server/domain/teacher_requests.py +0 -0
  325. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/server/platform/__init__.py +0 -0
  326. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/server/platform/auth.py +0 -0
  327. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/server/platform/db.py +0 -0
  328. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/server/platform/deps.py +0 -0
  329. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/server/platform/internal_client.py +0 -0
  330. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/server/platform/locks.py +0 -0
  331. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/server/platform/runtime.py +0 -0
  332. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/server/routes/__init__.py +0 -0
  333. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/server/routes/envs.py +0 -0
  334. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/server/routes/meta.py +0 -0
  335. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/server/routes/runs.py +0 -0
  336. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/server/routes/teacher.py +0 -0
  337. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/teacher/__init__.py +0 -0
  338. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/teacher/limits.py +0 -0
  339. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/flash/teacher/retry_contract.py +0 -0
  340. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/scripts/build_dev_dist.py +0 -0
  341. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/scripts/check_file_size.py +0 -0
  342. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/scripts/check_function_size.py +0 -0
  343. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/scripts/check_verl_pin_exists.py +0 -0
  344. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/scripts/scrub_history.sh +0 -0
  345. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/__init__.py +0 -0
  346. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/_helpers/__init__.py +0 -0
  347. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/_helpers/profile.py +0 -0
  348. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/_helpers/runner.py +0 -0
  349. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/_helpers/specs.py +0 -0
  350. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/_helpers/teacher.py +0 -0
  351. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/_helpers/vast.py +0 -0
  352. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/conftest.py +0 -0
  353. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/fixtures/math_eval.jsonl +0 -0
  354. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/fixtures/math_train.jsonl +0 -0
  355. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/live/__init__.py +0 -0
  356. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/live/conftest.py +0 -0
  357. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/live/test_lambda_live.py +0 -0
  358. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/live/test_runpod_live.py +0 -0
  359. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/live/test_sft_thinking_render_live.py +0 -0
  360. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/live/test_vast_live.py +0 -0
  361. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_accounting_coverage.py +0 -0
  362. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_adapter_shard_completeness.py +0 -0
  363. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_agent_flash_cli_contract.py +0 -0
  364. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_algorithms.py +0 -0
  365. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_allocator.py +0 -0
  366. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_backend_common.py +0 -0
  367. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_backend_jobspec_contract.py +0 -0
  368. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_bake_kernel_cache.py +0 -0
  369. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_base_model_provenance.py +0 -0
  370. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_billing_retry.py +0 -0
  371. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_build_context_contract.py +0 -0
  372. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_cancel_remote.py +0 -0
  373. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_catalog_consistency.py +0 -0
  374. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_catalog_only_models.py +0 -0
  375. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_charge_pricing.py +0 -0
  376. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_checkpoints.py +0 -0
  377. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_cli_commands_coverage.py +0 -0
  378. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_cli_credential_shadowing.py +0 -0
  379. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_cli_errors.py +0 -0
  380. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_cli_estimate.py +0 -0
  381. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_cli_gpus_flag.py +0 -0
  382. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_cli_help.py +0 -0
  383. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_cli_main_coverage.py +0 -0
  384. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_cli_managed.py +0 -0
  385. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_cli_render_coverage.py +0 -0
  386. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_cli_render_theme.py +0 -0
  387. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_cli_traces.py +0 -0
  388. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_cli_wandb_warning.py +0 -0
  389. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_client.py +0 -0
  390. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_client_import_purity.py +0 -0
  391. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_client_server_integration.py +0 -0
  392. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_client_stream_reads.py +0 -0
  393. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_config_env_vars.py +0 -0
  394. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_config_overrides.py +0 -0
  395. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_controlled_experiment_repairs.py +0 -0
  396. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_cost_analytical.py +0 -0
  397. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_cost_equation.py +0 -0
  398. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_cost_estimate.py +0 -0
  399. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_cost_hardware.py +0 -0
  400. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_cost_models.py +0 -0
  401. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_dataset_profile.py +0 -0
  402. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_deploy_alias_move_warning.py +0 -0
  403. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_deploy_latency.py +0 -0
  404. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_dev_channel.py +0 -0
  405. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_disk_gb.py +0 -0
  406. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_endpoint_name.py +0 -0
  407. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_env_cache_evict.py +0 -0
  408. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_env_delete.py +0 -0
  409. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_env_download.py +0 -0
  410. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_env_download_api.py +0 -0
  411. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_env_list_api.py +0 -0
  412. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_env_list_cli.py +0 -0
  413. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_env_list_hub.py +0 -0
  414. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_env_no_install.py +0 -0
  415. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_env_publish.py +0 -0
  416. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_env_pull.py +0 -0
  417. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_env_pull_coverage.py +0 -0
  418. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_env_pull_loader_coverage.py +0 -0
  419. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_env_pull_managed_control_plane.py +0 -0
  420. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_env_push.py +0 -0
  421. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_env_rate_limit_resolve.py +0 -0
  422. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_env_ref_pinning.py +0 -0
  423. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_envs_coverage.py +0 -0
  424. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_export.py +0 -0
  425. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_flash_mvp.py +0 -0
  426. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_flash_worker.py +0 -0
  427. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_flashinfer_cache_dirs.py +0 -0
  428. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_freesolo_api_transport.py +0 -0
  429. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_github_urlopen_retry.py +0 -0
  430. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_gpu_type_single_field.py +0 -0
  431. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_gpus.py +0 -0
  432. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_grpo_params.py +0 -0
  433. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_grpo_resident_sizing.py +0 -0
  434. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_grpo_reward_batching.py +0 -0
  435. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_health_liveness.py +0 -0
  436. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_hf_retry.py +0 -0
  437. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_idle_endpoint_reaper.py +0 -0
  438. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_infisical_secrets.py +0 -0
  439. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_instance_bootstrap_coverage.py +0 -0
  440. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_internal_client.py +0 -0
  441. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_jobs.py +0 -0
  442. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_kernel_cache.py +0 -0
  443. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_kernel_fingerprint.py +0 -0
  444. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_kv_util.py +0 -0
  445. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_lambda_api_coverage.py +0 -0
  446. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_lambda_runner.py +0 -0
  447. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_logging.py +0 -0
  448. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_login_perms.py +0 -0
  449. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_lora_rank_coverage.py +0 -0
  450. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_lora_rank_preflight.py +0 -0
  451. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_managed_config_fields.py +0 -0
  452. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_managed_hf_repo.py +0 -0
  453. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_metrics_schema_agent_contract.py +0 -0
  454. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_mig_guard.py +0 -0
  455. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_multi_gpu_gate.py +0 -0
  456. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_multimodal_training.py +0 -0
  457. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_named_reward_metrics.py +0 -0
  458. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_oom_escalate_gpu.py +0 -0
  459. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_opd.py +0 -0
  460. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_opd_limits.py +0 -0
  461. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_opd_multiturn_eos_boundary.py +0 -0
  462. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_opd_resume_safety.py +0 -0
  463. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_opd_train.py +0 -0
  464. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_orchestrator_flash.py +0 -0
  465. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_packing.py +0 -0
  466. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_packing_coverage.py +0 -0
  467. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_parasail_teacher.py +0 -0
  468. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_poll_helpers.py +0 -0
  469. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_preflight.py +0 -0
  470. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_projects.py +0 -0
  471. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_provider_preflight_coverage.py +0 -0
  472. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_provider_routing.py +0 -0
  473. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_provider_teardown_robustness.py +0 -0
  474. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_providers_symmetry.py +0 -0
  475. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_realized_cost.py +0 -0
  476. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_repo_cleanup.py +0 -0
  477. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_resolve_params_b.py +0 -0
  478. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_resume_on_retry.py +0 -0
  479. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_rl_train.py +0 -0
  480. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_rollout_samples.py +0 -0
  481. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_runmgmt.py +0 -0
  482. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_runpod_api_delete.py +0 -0
  483. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_runpod_key_fingerprint.py +0 -0
  484. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_runpod_key_waterfall.py +0 -0
  485. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_serve_reasoning_content.py +0 -0
  486. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_server_app_coverage.py +0 -0
  487. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_server_auth_singleflight.py +0 -0
  488. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_server_billing.py +0 -0
  489. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_server_checkpoints_coverage.py +0 -0
  490. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_server_db.py +0 -0
  491. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_server_locks_coverage.py +0 -0
  492. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_server_standalone.py +0 -0
  493. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_serving_context_preflight.py +0 -0
  494. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_serving_contract.py +0 -0
  495. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_serving_schema_coverage.py +0 -0
  496. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_sft_chunked_nll.py +0 -0
  497. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_sft_example_selection.py +0 -0
  498. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_sft_gc_off.py +0 -0
  499. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_sft_max_context.py +0 -0
  500. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_sft_startup_block.py +0 -0
  501. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_sft_train.py +0 -0
  502. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_sft_workload.py +0 -0
  503. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_spec_and_validation.py +0 -0
  504. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_step_floor.py +0 -0
  505. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_step_metrics.py +0 -0
  506. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_step_timing.py +0 -0
  507. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_structured_outputs.py +0 -0
  508. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_teacher_broker.py +0 -0
  509. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_teacher_encoding_contract.py +0 -0
  510. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_thinking_config.py +0 -0
  511. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_train_context_preflight.py +0 -0
  512. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_training_controls.py +0 -0
  513. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_type_comment_prose.py +0 -0
  514. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_vast_api.py +0 -0
  515. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_vast_api_coverage.py +0 -0
  516. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_vast_offers.py +0 -0
  517. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_vast_provider_coverage.py +0 -0
  518. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_vast_runner.py +0 -0
  519. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_verified_revisions.py +0 -0
  520. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_verifiers.py +0 -0
  521. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_version.py +0 -0
  522. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_vl_warmstart_adapter_keys.py +0 -0
  523. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_vram_architecture.py +0 -0
  524. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_wandb_link.py +0 -0
  525. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_wandb_naming.py +0 -0
  526. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_warmstart_adapter_download.py +0 -0
  527. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_warmstart_cross_repo.py +0 -0
  528. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_warmstart_error_attribution.py +0 -0
  529. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_weight_cache.py +0 -0
  530. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_worker_dryrun.py +0 -0
  531. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_worker_hardexit.py +0 -0
  532. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_worker_image.py +0 -0
  533. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_worker_init_heartbeat.py +0 -0
  534. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_worker_stack.py +0 -0
  535. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_worker_thinking.py +0 -0
  536. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_workflow_contracts.py +0 -0
  537. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/tests/test_workload_profile.py +0 -0
  538. {freesolo_flash_dev-1.2.33 → freesolo_flash_dev-1.2.36}/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.33
3
+ Version: 1.2.36
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
@@ -738,11 +738,11 @@ def _add_deployment_commands(models_sub: argparse._SubParsersAction) -> None:
738
738
  "--wait",
739
739
  nargs="?",
740
740
  type=_wait_seconds,
741
- const=1800.0,
741
+ const=2400.0,
742
742
  default=None,
743
743
  metavar="SECONDS",
744
744
  help=(
745
- "block until the requested revision is ready or failed (default timeout 1800s). "
745
+ "block until the requested revision is ready or failed (default timeout 2400s). "
746
746
  "without it, deploy returns while the revision is still queued"
747
747
  ),
748
748
  )
@@ -13,9 +13,11 @@ from __future__ import annotations
13
13
 
14
14
  import contextlib
15
15
  import inspect
16
+ import sys
16
17
 
17
18
  from flash.cli.commands.env.test_evaluations import _evaluation_example
18
- from flash.envs.evaluations import EvalCase, EvalResult
19
+ from flash.cli.ui import render
20
+ from flash.envs.evaluations import EvalCase, EvalResult, _episode_grading_enabled
19
21
 
20
22
 
21
23
  def _eval_module():
@@ -34,7 +36,7 @@ def _grades_episodes(suite) -> bool:
34
36
  Keying off the environment scored the wrong turn there and turned a well-formed first action
35
37
  into an error, so the suite has to say so itself.
36
38
  """
37
- return bool(getattr(suite, "grades_episodes", False))
39
+ return _episode_grading_enabled(suite)
38
40
 
39
41
 
40
42
  def _drive_episode(client, target: str, environment, case: EvalCase, args) -> dict | str:
@@ -123,7 +125,14 @@ def _effective_turn_cap(environment, state: dict) -> int:
123
125
 
124
126
 
125
127
  def _score_episode_case(
126
- suite, case: EvalCase, case_id: str, state: dict, *, thinking: bool = False
128
+ suite,
129
+ case: EvalCase,
130
+ case_id: str,
131
+ state: dict,
132
+ *,
133
+ scorer,
134
+ state_style: str | None,
135
+ thinking: bool = False,
127
136
  ) -> EvalResult:
128
137
  """Grade a finished episode through the suite's own scorer.
129
138
 
@@ -134,18 +143,19 @@ def _score_episode_case(
134
143
  `reward(completion, example, state)`, which is what reaches the SDK's `score_episodes`.
135
144
 
136
145
  `EvalSuite.score(case, response)` is the published two-argument contract, so state is offered
137
- only to a suite that accepts it, detected by signature rather than by try/except: a TypeError
138
- raised INSIDE a scorer that does accept state would otherwise be silently retried as a
139
- two-argument call and graded on the wrong text.
146
+ only to a suite that accepts it. The caller resolves one scorer and signature style for the
147
+ whole suite rather than retrying on TypeError: an error raised INSIDE a state-aware scorer must
148
+ not be retried as a two-argument call and graded on the wrong text.
140
149
  """
141
150
  response = state.get("response_text")
142
151
  if not isinstance(response, str):
143
152
  turns = state.get("turns") or []
144
153
  response = str(turns[-1]) if turns else ""
145
154
  eval_module = _eval_module()
146
- style = _state_argument(getattr(suite, "score", None))
147
- if style is None:
148
- return eval_module._score_case(suite, case, case_id, response, thinking=thinking)
155
+ if state_style is None:
156
+ return eval_module._score_case(
157
+ suite, case, case_id, response, thinking=thinking, scorer=scorer
158
+ )
149
159
  return eval_module._score_case(
150
160
  suite,
151
161
  case,
@@ -153,7 +163,8 @@ def _score_episode_case(
153
163
  response,
154
164
  thinking=thinking,
155
165
  state=state,
156
- state_keyword=style == "keyword",
166
+ state_keyword=state_style == "keyword",
167
+ scorer=scorer,
157
168
  )
158
169
 
159
170
 
@@ -173,27 +184,45 @@ def _state_argument(score) -> str | None:
173
184
  except (TypeError, ValueError):
174
185
  # builtins and C callables expose no signature; treat them as the published contract.
175
186
  return None
176
- named_state = next((p for p in parameters if p.name == "state"), None)
177
- if named_state is not None and named_state.kind in (
178
- inspect.Parameter.KEYWORD_ONLY,
179
- inspect.Parameter.POSITIONAL_OR_KEYWORD,
180
- ):
181
- # By keyword even where positional would also bind: it cannot land on the wrong parameter.
182
- return "keyword"
183
- # Checked before `*args`, since a scorer with both can take `state=` but one with only
184
- # `*args` cannot.
185
- if any(p.kind is inspect.Parameter.VAR_KEYWORD for p in parameters):
186
- return "keyword"
187
- if any(p.kind is inspect.Parameter.VAR_POSITIONAL for p in parameters):
188
- return "positional"
189
187
  positional = [
190
- p
191
- for p in parameters
192
- if p.kind in (inspect.Parameter.POSITIONAL_ONLY, inspect.Parameter.POSITIONAL_OR_KEYWORD)
188
+ parameter
189
+ for parameter in parameters
190
+ if parameter.kind
191
+ in (inspect.Parameter.POSITIONAL_ONLY, inspect.Parameter.POSITIONAL_OR_KEYWORD)
193
192
  ]
194
- # (case, response) is the published contract; a third positional is the episode state. This
195
- # also catches a positional-only `state`, which the named check above deliberately skips.
196
- return "positional" if len(positional) >= 3 else None
193
+ named_state = next((parameter for parameter in parameters if parameter.name == "state"), None)
194
+ if named_state is not None:
195
+ if named_state.kind is inspect.Parameter.POSITIONAL_ONLY:
196
+ return "positional" if positional.index(named_state) == 2 else None
197
+ if named_state.kind in (
198
+ inspect.Parameter.KEYWORD_ONLY,
199
+ inspect.Parameter.POSITIONAL_OR_KEYWORD,
200
+ ):
201
+ # by keyword even where positional would also bind: it cannot land on the wrong parameter.
202
+ return "keyword"
203
+ # checked before `*args`, since a scorer with both can take `state=` but one with only
204
+ # `*args` cannot.
205
+ if any(parameter.kind is inspect.Parameter.VAR_KEYWORD for parameter in parameters):
206
+ return "keyword"
207
+ if any(parameter.kind is inspect.Parameter.VAR_POSITIONAL for parameter in parameters):
208
+ # scorer(case, response, state) reaches *args when the signature has no fixed third slot.
209
+ # zero, one, or two regular positional parameters can all bind that call.
210
+ return "positional" if len(positional) <= 2 else None
211
+ return None
212
+
213
+
214
+ def _warn_if_episode_state_is_hidden(suite, state_style: str | None) -> None:
215
+ """Warn once when full-episode work feeds a scorer that cannot see the transcript."""
216
+ if state_style is not None:
217
+ return
218
+ message = (
219
+ f"suite {getattr(suite, 'name', 'evaluation')!r} sets grades_episodes = True; "
220
+ "each episode will still be played out with one generation per turn, but the scorer "
221
+ "will receive only the episode's final response text, not the transcript. Add a third "
222
+ "`state` argument to "
223
+ "`score(case, response, state)` to grade the transcript."
224
+ )
225
+ print(render.warn(message) if render.styled() else f"warning: {message}", file=sys.stderr)
197
226
 
198
227
 
199
228
  def _run_episode_cases(
@@ -220,6 +249,9 @@ def _run_episode_cases(
220
249
  )
221
250
  for case_id in case_ids
222
251
  )
252
+ scorer = getattr(suite, "score", None)
253
+ state_style = _state_argument(scorer)
254
+ _warn_if_episode_state_is_hidden(suite, state_style)
223
255
  results = []
224
256
  # The adapter defaults to `thinking = False` (flash/envs/adapter.py), and with it off
225
257
  # `_scored_turn_text` returns the turn unstripped -- so `state["response_text"]` keeps its
@@ -237,7 +269,17 @@ def _run_episode_cases(
237
269
  if isinstance(outcome, str):
238
270
  results.append(eval_module._generation_error(case_id, outcome))
239
271
  continue
240
- results.append(_score_episode_case(suite, case, case_id, outcome, thinking=thinking))
272
+ results.append(
273
+ _score_episode_case(
274
+ suite,
275
+ case,
276
+ case_id,
277
+ outcome,
278
+ scorer=scorer,
279
+ state_style=state_style,
280
+ thinking=thinking,
281
+ )
282
+ )
241
283
  return tuple(results)
242
284
 
243
285
 
@@ -162,6 +162,7 @@ def _score_case(
162
162
  thinking: bool = False,
163
163
  state=None,
164
164
  state_keyword: bool = False,
165
+ scorer=None,
165
166
  ) -> EvalResult:
166
167
  """Grade one response on the caller's thread.
167
168
 
@@ -172,7 +173,8 @@ def _score_case(
172
173
  `episode._score_episode_case`); single-turn scoring keeps the two-argument contract.
173
174
  `state_keyword` says which way that suite's signature can take it -- `**kwargs` and
174
175
  keyword-only scorers reject a third positional, `*args` scorers reject the keyword -- so the
175
- caller decides, having read the signature.
176
+ caller decides, having read the signature. Episode scoring also passes the exact callable it
177
+ inspected, so a descriptor cannot change shape between capability detection and invocation.
176
178
 
177
179
  The scorer grades the stripped answer; the RESULT records the raw generation. Stripping for the
178
180
  scorer must not shorten what is recorded, on the error path least of all -- a failed case is
@@ -182,12 +184,13 @@ def _score_case(
182
184
  try:
183
185
  scored_text = _scored_response(response, thinking=thinking)
184
186
  recorded_response = getattr(scored_text, "raw", response)
187
+ score = suite.score if scorer is None else scorer
185
188
  if state is None:
186
- scored = suite.score(case, scored_text)
189
+ scored = score(case, scored_text)
187
190
  elif state_keyword:
188
- scored = suite.score(case, scored_text, state=state)
191
+ scored = score(case, scored_text, state=state)
189
192
  else:
190
- scored = suite.score(case, scored_text, state)
193
+ scored = score(case, scored_text, state)
191
194
  return normalize_eval_result(case, recorded_response, scored, case_id=case_id)
192
195
  except (Exception, SystemExit) as exc:
193
196
  return EvalResult(
@@ -138,12 +138,14 @@ Given the opening prompt, does the model emit the single integer `step_episode`
138
138
  to advance the game? That is a real held-out check of the action format the episode
139
139
  depends on, and it is the honest scope of a single-shot evaluation.
140
140
 
141
- To grade a finished transcript instead, set `grades_episodes = True` on the suite.
142
- `env eval` then plays each case out against the deployed model -- generating, stepping
143
- the environment, and repeating to `max_episode_turns` -- and scores the resulting
144
- transcript. Such a suite needs cases the environment can actually advance (the cases
145
- below carry no `output`, so `step_episode` has no secret to compare against), and each
146
- case then costs one generation per turn rather than one in total.
141
+ To grade a finished transcript instead, set `grades_episodes = True` on the suite
142
+ and define `score(self, case, response, state)`. `env eval` then plays each case out
143
+ against the deployed model -- generating, stepping the environment, and repeating to
144
+ `max_episode_turns` -- and passes the resulting transcript in `state`; without that
145
+ argument the scorer receives only the episode's final response text. Such a suite
146
+ needs cases the environment can actually advance (the cases below carry no `output`,
147
+ so `step_episode` has no secret to compare against), and each case then costs one
148
+ generation per turn rather than one in total.
147
149
 
148
150
  Do NOT grade these by calling `environment.reward(response, example)`: with no episode
149
151
  state that call scores an empty transcript, so an unrelated answer can score 1.0 and
@@ -289,7 +291,7 @@ class StarterMultiTurnEnv(EnvironmentMultiTurn):
289
291
  # Advance the world after one assistant action. Return done=True to end the
290
292
  # episode, or append an observation message and keep going.
291
293
  # `messages` already ends with this action: messages[-1]["content"] is
292
- # `assistant_response`. If you rebuild state by replaying the transcript, replay
294
+ # `assistant_response`. if you rebuild state by replaying the transcript, replay
293
295
  # `messages[:-1]` and apply `assistant_response` once, or you apply it twice.
294
296
  try:
295
297
  guess = int(assistant_response.strip().split()[0])
@@ -9,7 +9,10 @@ from pathlib import Path
9
9
 
10
10
  from flash.cli.commands.env.episode import _effective_turn_cap
11
11
  from flash.cli.commands.env.push import _err, _resolve_local_env_entrypoint
12
- from flash.cli.commands.env.test_evaluations import _check_evaluation_suites
12
+ from flash.cli.commands.env.test_evaluations import (
13
+ _check_evaluation_suites,
14
+ _normalize_prompt_images,
15
+ )
13
16
  from flash.cli.commands.env.test_params import _env_params
14
17
  from flash.cli.commands.env.test_warnings import (
15
18
  _warn_on_low_replay_reward,
@@ -265,9 +268,20 @@ def _drive_single_turn(env, example: dict, record: dict, *, force_echo: bool = F
265
268
  )
266
269
 
267
270
 
268
- def _drive_multi_turn(env, example: dict, record: dict, *, force_echo: bool = False) -> None:
271
+ def _new_multi_turn_replay_state(env, example: dict, record: dict) -> dict:
269
272
  state = env.new_rollout_state(example)
270
273
  record["prompt"] = _check_messages(state.get("prompt") or state.get("messages"), "prompt")
274
+ _normalize_prompt_images(env, example, record["prompt"])
275
+ return state
276
+
277
+
278
+ def _validate_multi_turn_reply(env, example: dict, state: dict, messages: object) -> None:
279
+ _check_messages(messages, "env_reply")
280
+ _normalize_prompt_images(env, example, [dict(message) for message in state["messages"]])
281
+
282
+
283
+ def _drive_multi_turn(env, example: dict, record: dict, *, force_echo: bool = False) -> None:
284
+ state = _new_multi_turn_replay_state(env, example, record)
271
285
  completion = _gold_completion(env, example)
272
286
  record["completion"] = completion
273
287
  reference_turns = _reference_turns(completion)
@@ -326,18 +340,19 @@ def _drive_multi_turn(env, example: dict, record: dict, *, force_echo: bool = Fa
326
340
  break
327
341
  env_msgs = env.env_reply(state["messages"], state)
328
342
  env_step_pending = False
329
- if not env_msgs:
330
- break
331
- # the env's own reply messages feed the chat template for the next turn in the real
332
- # rollout, so validate their envelope here too: a malformed reply that would break
333
- # remotely must fail the episode instead of slipping through on a finite reward.
334
- _check_messages(env_msgs, "env_reply")
335
343
  if gold_finished is None and turns >= len(reference_turns):
336
344
  # the gold answer has just run out and its last turn is applied: this is the only
337
345
  # moment the reference can be judged on its own, before junk padding touches the state.
338
346
  gold_finished = _episode_completed(env, state, hard_cap)
347
+ if not env_msgs:
348
+ break
339
349
  if env.rollout_done(state, max_turns=hard_cap):
340
350
  break
351
+ # the env's own reply messages feed the chat template for the next turn in the real
352
+ # rollout, so validate their envelope and accumulated images here too: a malformed reply
353
+ # that would break remotely must fail the episode instead of slipping through on a finite
354
+ # reward. normalize copies so the check cannot replace authoritative rollout messages.
355
+ _validate_multi_turn_reply(env, example, state, env_msgs)
341
356
 
342
357
  # the driver-side exits above stop before the inter-turn env_reply, so the last replayed turn
343
358
  # is still unapplied. a stateful env would then score a board or transcript missing the last
@@ -351,18 +366,9 @@ def _drive_multi_turn(env, example: dict, record: dict, *, force_echo: bool = Fa
351
366
  # env that replied with nothing, a natural finish) -- stepping again there would be a spurious
352
367
  # extra move. rollout_done covers the env having declared the episode over.
353
368
  if env_step_pending and not env.rollout_done(state, hard_cap):
354
- # validated exactly like the in-loop replies above: a malformed reply breaks the chat
355
- # template on the paid run whether it was the last one or not. this call is the ONLY
356
- # env_reply for an episode stopped at the ceiling, and a per-example `max_episode_turns`
357
- # makes that the common case rather than a rare one -- leaving it unchecked let an env whose
358
- # final reply is malformed reach `overall: PASS`.
359
- #
360
- # an EMPTY reply is allowed first, exactly as the in-loop path does (`if not env_msgs:
361
- # break` precedes its own `_check_messages`): an env with nothing further to observe
362
- # legitimately returns nothing, and `_check_messages` rejects an empty list.
363
- final_msgs = env.env_reply(state["messages"], state)
364
- if final_msgs:
365
- _check_messages(final_msgs, "env_reply")
369
+ # apply the final action's side effects, but do not validate its reply as a future prompt:
370
+ # no later model generation consumes it in the online path.
371
+ env.env_reply(state["messages"], state)
366
372
  if gold_finished is None:
367
373
  # the gold answer never ran out inside the loop -- it covered the whole episode, so the
368
374
  # break came first and the mid-loop sample never fired. NOW is its moment: the deferred
@@ -1,12 +1,13 @@
1
1
  """Offline contract checks for an environment's evaluation sidecar.
2
2
 
3
- Split from `test.py` to keep that file under the 1000-line gate. This group is cohesive and has one
4
- entry point, `check_evaluation_suites`: everything else here exists to build one held-out case's
5
- prompt and replayed response the same way `flash env eval` would.
3
+ Split from `test.py` to keep that file under the 1000-line gate. Single-turn cases validate prompt
4
+ construction and reference replay. Episode cases validate initial rollout and prompt construction,
5
+ then bind the scorer signature without executing it against unfinished state.
6
6
  """
7
7
 
8
8
  from __future__ import annotations
9
9
 
10
+ import inspect
10
11
  from pathlib import Path
11
12
 
12
13
  from flash.cli.commands.env.push import _err
@@ -76,7 +77,41 @@ def _evaluation_response(env, case) -> tuple[str, str]:
76
77
  return policy, response
77
78
 
78
79
 
80
+ def _check_episode_evaluation_prompt(env, case) -> None:
81
+ """Validate the held-out case's initial rollout state and prompt without advancing it."""
82
+ # imported here rather than at module scope: `test.py` imports this module.
83
+ from flash.cli.commands.env.test import _new_multi_turn_replay_state, _new_record
84
+
85
+ _new_multi_turn_replay_state(env, _evaluation_example(case), _new_record())
86
+
87
+
88
+ def _validate_episode_scorer_signature(scorer, case, state_style: str | None) -> None:
89
+ """Bind the online scorer call shape without executing it against unfinished state."""
90
+ if not callable(scorer):
91
+ raise TypeError("evaluation suite score must be callable")
92
+ try:
93
+ signature = inspect.signature(scorer)
94
+ except (TypeError, ValueError):
95
+ # some builtins and extension callables expose no signature, so keep the permissive runtime
96
+ # behavior without calling them during an offline check.
97
+ return
98
+
99
+ response = "response"
100
+ state = {}
101
+ if state_style is None:
102
+ signature.bind(case, response)
103
+ elif state_style == "keyword":
104
+ signature.bind(case, response, state=state)
105
+ else:
106
+ signature.bind(case, response, state)
107
+
108
+
79
109
  def _check_evaluation_suites(entrypoint: Path, env) -> bool:
110
+ from flash.cli.commands.env.episode import (
111
+ _grades_episodes,
112
+ _state_argument,
113
+ _warn_if_episode_state_is_hidden,
114
+ )
80
115
  from flash.envs.evaluations import (
81
116
  _DEFAULT_EVALUATIONS_PATH,
82
117
  EvalSuiteReport,
@@ -107,9 +142,28 @@ def _check_evaluation_suites(entrypoint: Path, env) -> bool:
107
142
  f"evaluation suite {suite.name} failed contract checks: suite produced no cases"
108
143
  )
109
144
  continue
145
+ episode_suite = _grades_episodes(suite)
146
+ if episode_suite and not getattr(env, "multi_turn", False):
147
+ raise TypeError(
148
+ "suite sets grades_episodes = True, but this environment is single-turn "
149
+ "and has no episode to play"
150
+ )
151
+ scorer = getattr(suite, "score", None)
152
+ if episode_suite:
153
+ state_style = _state_argument(scorer)
154
+ _warn_if_episode_state_is_hidden(suite, state_style)
155
+ for case in cases:
156
+ _check_episode_evaluation_prompt(env, case)
157
+ _validate_episode_scorer_signature(scorer, cases[0], state_style)
158
+ print(
159
+ f"evaluation suite {suite.name}: {len(cases)}/{len(cases)} cases "
160
+ "passed contract checks"
161
+ )
162
+ continue
163
+
110
164
  for index, case in enumerate(cases, start=1):
111
165
  _policy, response = _evaluation_response(env, case)
112
- scored = suite.score(case, response)
166
+ scored = scorer(case, response)
113
167
  result = normalize_eval_result(
114
168
  case,
115
169
  response,
@@ -224,6 +224,11 @@ int, `strict=true` as a bool, and anything that does not parse as a TOML scalar
224
224
  `flash env eval` takes the same two flags, for the same reason: a held-out suite scored
225
225
  against a differently-configured environment is not measuring your run.
226
226
 
227
+ For a multi-turn environment, `flash env eval` still defaults to one prompt and one reply, which is
228
+ a valid first-action check. Set `grades_episodes = True` on a suite to play one generation per turn.
229
+ A scorer with the recommended `score(case, response, state)` signature receives the finished
230
+ transcript state; otherwise the scorer receives only the episode's final response text.
231
+
227
232
  **It is also a three-example smoke test, not a dataset audit.** `flash env test` runs the
228
233
  contract checks against the **first 3 rows only** (`_DEFAULT_EPISODES = 3`, and it iterates
229
234
  `dataset[:episode_count]`), so a malformed prompt, a scorer that raises, or a bad episode
@@ -124,15 +124,35 @@ class EvalSuiteReport:
124
124
 
125
125
  @runtime_checkable
126
126
  class EvalSuite(Protocol):
127
- """Authoring contract for one named held-out evaluation suite."""
127
+ """Authoring contract for a suite that grades one model response."""
128
128
 
129
- name: str
129
+ @property
130
+ def name(self) -> str: ...
130
131
 
131
132
  def cases(self) -> list[EvalCase]: ...
132
133
 
133
134
  def score(self, case: EvalCase, response: str) -> EvalResult | float | bool: ...
134
135
 
135
136
 
137
+ class EpisodeEvalSuite(Protocol):
138
+ """Suite contract for full-episode play at one generation per turn.
139
+
140
+ ``grades_episodes`` must be true at runtime. The finished transcript is passed in ``state``.
141
+ """
142
+
143
+ @property
144
+ def name(self) -> str: ...
145
+
146
+ grades_episodes: bool
147
+
148
+ def cases(self) -> list[EvalCase]: ...
149
+
150
+ def score(self, case: EvalCase, response: str, state: dict) -> EvalResult | float | bool: ...
151
+
152
+
153
+ EvaluationSuite = EvalSuite | EpisodeEvalSuite
154
+
155
+
136
156
  class BaseEvalSuite:
137
157
  """Convenience base with expected-answer substring scoring."""
138
158
 
@@ -194,8 +214,20 @@ def normalize_eval_result(
194
214
  )
195
215
 
196
216
 
197
- def validate_evaluation_cases(suite: EvalSuite, *, source: str | Path) -> list[EvalCase]:
217
+ def _episode_grading_enabled(suite: EvaluationSuite) -> bool:
218
+ """Return the validated full-episode grading opt-in."""
219
+ value = getattr(suite, "grades_episodes", False)
220
+ if not isinstance(value, bool):
221
+ name = getattr(suite, "name", "evaluation")
222
+ raise TypeError(
223
+ f"suite {name!r} grades_episodes must be a bool, got {type(value).__name__}"
224
+ )
225
+ return value
226
+
227
+
228
+ def validate_evaluation_cases(suite: EvaluationSuite, *, source: str | Path) -> list[EvalCase]:
198
229
  """Load and validate one suite's cases with source-aware errors."""
230
+ _episode_grading_enabled(suite)
199
231
  try:
200
232
  cases = suite.cases()
201
233
  except Exception as exc:
@@ -398,7 +430,7 @@ class _ScopedSuite:
398
430
 
399
431
  __slots__ = ("_module_dir", "_suite")
400
432
 
401
- def __init__(self, suite: EvalSuite, module_dir: str) -> None:
433
+ def __init__(self, suite: EvaluationSuite, module_dir: str) -> None:
402
434
  self._suite = suite
403
435
  self._module_dir = module_dir
404
436
 
@@ -492,7 +524,7 @@ def _call_factory(factory, kwargs: dict[str, object]) -> object:
492
524
  return factory(*positional, **filtered_kwargs)
493
525
 
494
526
 
495
- def _validate_suites(value: object, *, source: Path) -> list[EvalSuite]:
527
+ def _validate_suites(value: object, *, source: Path) -> list[EvaluationSuite]:
496
528
  if not isinstance(value, (list, tuple)):
497
529
  raise TypeError(
498
530
  f"{source}: expected {_DEFAULT_EVALUATIONS_FACTORY}() or EVALUATIONS "
@@ -503,7 +535,7 @@ def _validate_suites(value: object, *, source: Path) -> list[EvalSuite]:
503
535
  f"{source}: expected at least one evaluation suite from "
504
536
  f"{_DEFAULT_EVALUATIONS_FACTORY}() or EVALUATIONS"
505
537
  )
506
- suites: list[EvalSuite] = []
538
+ suites: list[EvaluationSuite] = []
507
539
  names: set[str] = set()
508
540
  for index, suite in enumerate(value, start=1):
509
541
  name = getattr(suite, "name", None)
@@ -526,7 +558,7 @@ def _validate_suites(value: object, *, source: Path) -> list[EvalSuite]:
526
558
 
527
559
  def load_evaluation_suites(
528
560
  env_ref_or_path: str | Path, *, environment: object | None = None
529
- ) -> list[EvalSuite]:
561
+ ) -> list[EvaluationSuite]:
530
562
  """Load evaluations.py beside a resolved environment entrypoint."""
531
563
  source = _evaluation_path(env_ref_or_path)
532
564
  if not source.is_file():
@@ -574,10 +606,12 @@ def load_evaluation_suites(
574
606
  __all__ = [
575
607
  "_DEFAULT_EVALUATIONS_PATH",
576
608
  "BaseEvalSuite",
609
+ "EpisodeEvalSuite",
577
610
  "EvalCase",
578
611
  "EvalResult",
579
612
  "EvalSuite",
580
613
  "EvalSuiteReport",
614
+ "EvaluationSuite",
581
615
  "_evaluation_path",
582
616
  "has_evaluations",
583
617
  "load_evaluation_suites",
@@ -195,6 +195,25 @@ def mark_deployment_pending(
195
195
  return status
196
196
 
197
197
 
198
+ def _confirmed_active_failed_predecessor(deployment: object, run_id: str) -> bool:
199
+ if not isinstance(deployment, dict):
200
+ return False
201
+ revision = deployment.get("adapter_revision")
202
+ parsed = parse_adapter_revision(revision) if isinstance(revision, str) else None
203
+ return (
204
+ deployment.get("state") == "failed"
205
+ and deployment.get("alias_activation_confirmed") is True
206
+ and parsed is not None
207
+ and parsed[0] == run_id
208
+ )
209
+
210
+
211
+ def _restorable_deployment_predecessor(deployment: object, run_id: str) -> bool:
212
+ return (
213
+ isinstance(deployment, dict) and deployment.get("state") in _RESTORABLE_DEPLOYMENT_STATES
214
+ ) or _confirmed_active_failed_predecessor(deployment, run_id)
215
+
216
+
198
217
  def mark_deployment_failed(run_id: str, deployment: dict) -> RunStatus:
199
218
  """Record a failed deployment attempt while preserving the run lifecycle state."""
200
219
  from flash.runner import _save_status_unlocked, _status_guard, get_status
@@ -212,10 +231,12 @@ def mark_deployment_failed(run_id: str, deployment: dict) -> RunStatus:
212
231
  ):
213
232
  return status
214
233
  previous = deployment.get("previous_deployment")
215
- if (
234
+ if _restorable_deployment_predecessor(previous, run_id) and (
216
235
  not deployment.get("activation_outcome_unknown")
217
- and isinstance(previous, dict)
218
- and previous.get("state") in _RESTORABLE_DEPLOYMENT_STATES
236
+ or (
237
+ deployment.get("state") == "failed"
238
+ and _confirmed_active_failed_predecessor(previous, run_id)
239
+ )
219
240
  ):
220
241
  status.deployment = {
221
242
  **previous,
@@ -23,6 +23,7 @@ from flash.serve.errors import ( # noqa: F401 -- re-exported: callers import th
23
23
  ActivationOutcomeUnknown,
24
24
  AdapterConfigMissing,
25
25
  AdapterTensorMissing,
26
+ AliasThinkingSilent,
26
27
  RetryableServingUnavailable,
27
28
  ServingError,
28
29
  )
@@ -67,14 +68,15 @@ READBACK_MAX_DELAY_SECONDS = 2.0
67
68
  # with margin. the floor is doubled to 10 and the per-B term covers a bigger base on top.
68
69
  #
69
70
  # the cap is the real constraint, and readiness is only one leg of the attempt. the same deploy also
70
- # spends time BEFORE this wait (resolving the hub revision, downloading the adapter config to read
71
- # its rank, the capability check, registration) and AFTER it (`_SMOKE_BUDGET_SECONDS` = 600s of
72
- # smoke, then activation). the whole attempt must finish inside BOTH `_DEPLOYMENT_STALE_SECONDS`
73
- # (1800s, when the plane declares an in-flight attempt abandoned) and the CLI's 1800s default
74
- # `--wait`, or a deploy that is still progressing is reaped or reported as failed.
71
+ # spends time before this wait (resolving the hub revision, downloading the adapter config to read
72
+ # its rank, the capability check, registration) and after it (600s of immutable smoke, activation,
73
+ # then 600s of alias smoke). the whole attempt must finish inside both
74
+ # `_DEPLOYMENT_STALE_SECONDS` (2400s, when the plane declares an in-flight attempt abandoned) and
75
+ # the CLI's 2400s default `--wait`, or a deploy that is still progressing is reaped or reported as
76
+ # failed.
75
77
  #
76
- # so the cap leaves real slack rather than just clearing smoke: 900 + 600 = 1500, keeping 300s for
77
- # the surrounding hub reads, registration, activation, and poll latency, none of which share a
78
+ # so the cap leaves real slack rather than just clearing smoke: 900 + 600 + 600 = 2100, keeping 300s
79
+ # for the surrounding hub reads, registration, activation, and poll latency, none of which share a
78
80
  # wall-clock bound with this one.
79
81
  #
80
82
  # a longer budget costs little: an adapter serving REJECTS raises as soon as the revision reports
@@ -818,6 +820,7 @@ def _retryable_smoke_unavailable(
818
820
  response: httpx.Response,
819
821
  *,
820
822
  requested_model: str,
823
+ expected_adapter_revision: str,
821
824
  ) -> RetryableServingUnavailable | None:
822
825
  if response.status_code != 503:
823
826
  return None
@@ -834,7 +837,7 @@ def _retryable_smoke_unavailable(
834
837
  or error.get("retryable") is not True
835
838
  or code not in _RETRYABLE_SMOKE_503_CODES
836
839
  or error.get("requested_model") != requested_model
837
- or error.get("adapter_revision") != requested_model
840
+ or error.get("adapter_revision") != expected_adapter_revision
838
841
  ):
839
842
  return None
840
843
  raw_delay = response.headers.get("Retry-After") or error.get("retry_after_seconds")
@@ -854,6 +857,7 @@ def chat(
854
857
  max_tokens: int = 512,
855
858
  thinking: bool = False,
856
859
  expected_checkpoint: str | None = None,
860
+ expected_adapter_revision: str | None = None,
857
861
  timeout_s: float | None = None,
858
862
  retry_unavailable: bool = False,
859
863
  stop: list[str] | None = None,
@@ -887,7 +891,11 @@ def chat(
887
891
  with client_context as client:
888
892
  resp = client.post(f"{base}/chat/completions", json=body, headers=headers, timeout=timeout)
889
893
  if retry_unavailable:
890
- retryable_error = _retryable_smoke_unavailable(resp, requested_model=run_id)
894
+ retryable_error = _retryable_smoke_unavailable(
895
+ resp,
896
+ requested_model=run_id,
897
+ expected_adapter_revision=expected_adapter_revision or run_id,
898
+ )
891
899
  if retryable_error is not None:
892
900
  raise retryable_error
893
901
  resp.raise_for_status()