freesolo-flash-dev 1.0.26__tar.gz → 1.0.28__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 (385) hide show
  1. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/PKG-INFO +1 -1
  2. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/worker/opd_verl.py +15 -3
  3. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/worker/rl_verl.py +144 -55
  4. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/pyproject.toml +2 -2
  5. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_opd_verl.py +5 -1
  6. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_rl_verl.py +143 -4
  7. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/uv.lock +1 -1
  8. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/.claude/skills/verify/SKILL.md +0 -0
  9. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/.dockerignore +0 -0
  10. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/.env.example +0 -0
  11. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/.github/workflows/auto-rebake.yml +0 -0
  12. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/.github/workflows/bake-kernel-cache.yml +0 -0
  13. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/.github/workflows/ci.yml +0 -0
  14. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/.github/workflows/main-source-guard.yml +0 -0
  15. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/.github/workflows/notify-tests-repo.yml +0 -0
  16. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/.github/workflows/publish-dev.yml +0 -0
  17. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/.github/workflows/publish-image.yml +0 -0
  18. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/.github/workflows/publish.yml +0 -0
  19. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/.github/workflows/version-parity.yml +0 -0
  20. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/.github/workflows/worker-image.yml +0 -0
  21. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/.gitignore +0 -0
  22. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/AB_PLAN.md +0 -0
  23. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/Dockerfile +0 -0
  24. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/Dockerfile.worker +0 -0
  25. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/LICENSE +0 -0
  26. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/README.md +0 -0
  27. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/build/kernel_cache/.gitignore +0 -0
  28. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/build/kernel_cache/.keep +0 -0
  29. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/docker/Dockerfile.kernelcache +0 -0
  30. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/docker/Dockerfile.kernelcache.relayer +0 -0
  31. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/docker/bake_kernel_cache.py +0 -0
  32. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/docker/bake_pod_entry.py +0 -0
  33. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/docker/kernel_fingerprint.py +0 -0
  34. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/docker/make_rp_handler.py +0 -0
  35. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/__init__.py +0 -0
  36. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/_channel.py +0 -0
  37. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/_fileio.py +0 -0
  38. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/_logging.py +0 -0
  39. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/_update_check.py +0 -0
  40. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/adapter_artifacts.py +0 -0
  41. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/catalog.py +0 -0
  42. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/cli/__init__.py +0 -0
  43. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/cli/__main__.py +0 -0
  44. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/cli/_tty.py +0 -0
  45. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/cli/commands.py +0 -0
  46. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/cli/env_setup.py +0 -0
  47. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/cli/env_test.py +0 -0
  48. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/cli/envpush.py +0 -0
  49. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/cli/render.py +0 -0
  50. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/cli/traces.py +0 -0
  51. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/cli/training_doc.py +0 -0
  52. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/client/__init__.py +0 -0
  53. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/client/config.py +0 -0
  54. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/client/http.py +0 -0
  55. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/client/runtime_secrets.py +0 -0
  56. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/client/specs.py +0 -0
  57. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/cost/__init__.py +0 -0
  58. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/cost/analytical.py +0 -0
  59. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/cost/facts.py +0 -0
  60. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/cost/spec.py +0 -0
  61. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/cost/types.py +0 -0
  62. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/diagnostics.py +0 -0
  63. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/__init__.py +0 -0
  64. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/accounting.py +0 -0
  65. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/chalk_kernels.py +0 -0
  66. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/multiturn_reward_scoring.py +0 -0
  67. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/multiturn_rollout.py +0 -0
  68. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/recipe.py +0 -0
  69. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/steps.py +0 -0
  70. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/structured_outputs.py +0 -0
  71. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/vram.py +0 -0
  72. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/worker/__init__.py +0 -0
  73. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/worker/__main__.py +0 -0
  74. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/worker/_pkg.py +0 -0
  75. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/worker/adapter.py +0 -0
  76. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/worker/decoding.py +0 -0
  77. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/worker/finalize.py +0 -0
  78. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/worker/gpu_setup.py +0 -0
  79. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/worker/grpo.py +0 -0
  80. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/worker/grpo_multimodal.py +0 -0
  81. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/worker/grpo_perturn_trainer.py +0 -0
  82. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/worker/heartbeat.py +0 -0
  83. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/worker/hf.py +0 -0
  84. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/worker/kernel_warmup.py +0 -0
  85. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/worker/lora.py +0 -0
  86. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/worker/opd.py +0 -0
  87. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/worker/opd_gkd.py +0 -0
  88. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/worker/opd_verl_multiturn.py +0 -0
  89. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/worker/opd_verl_plugin.py +0 -0
  90. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/worker/opd_verl_structured.py +0 -0
  91. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/worker/opd_vllm.py +0 -0
  92. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/worker/packing.py +0 -0
  93. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/worker/perf/__init__.py +0 -0
  94. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/worker/perf/attn.py +0 -0
  95. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/worker/perf/diagnostics.py +0 -0
  96. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/worker/perf/lifecycle.py +0 -0
  97. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/worker/perf/liger.py +0 -0
  98. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/worker/perf/loraplus.py +0 -0
  99. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/worker/perf/memory.py +0 -0
  100. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/worker/rl.py +0 -0
  101. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/worker/rng.py +0 -0
  102. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/worker/rollout_samples.py +0 -0
  103. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/worker/sft.py +0 -0
  104. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/worker/sft_verl.py +0 -0
  105. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/worker/teacher.py +0 -0
  106. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/worker/tokenizer_align.py +0 -0
  107. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/worker/verl_common.py +0 -0
  108. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/worker/wandb_log.py +0 -0
  109. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/engine/worker_entrypoint.py +0 -0
  110. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/envs/__init__.py +0 -0
  111. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/envs/adapter.py +0 -0
  112. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/envs/archive.py +0 -0
  113. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/envs/archive_policy.py +0 -0
  114. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/envs/base.py +0 -0
  115. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/envs/loader.py +0 -0
  116. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/envs/pull.py +0 -0
  117. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/envs/registry.py +0 -0
  118. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/lora_rank.py +0 -0
  119. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/multimodal.py +0 -0
  120. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/opd_retry_contract.py +0 -0
  121. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/opd_verl_validation.py +0 -0
  122. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/__init__.py +0 -0
  123. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/_auth.py +0 -0
  124. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/_deadline.py +0 -0
  125. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/_hf_artifacts.py +0 -0
  126. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/_hf_retry.py +0 -0
  127. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/_http.py +0 -0
  128. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/_instance.py +0 -0
  129. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/_instance_bootstrap.py +0 -0
  130. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/_instance_poll.py +0 -0
  131. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/_instance_provider.py +0 -0
  132. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/_poll.py +0 -0
  133. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/_worker.py +0 -0
  134. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/allocator.py +0 -0
  135. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/base.py +0 -0
  136. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/lambdalabs/__init__.py +0 -0
  137. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/lambdalabs/api.py +0 -0
  138. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/lambdalabs/auth.py +0 -0
  139. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/lambdalabs/gpus.py +0 -0
  140. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/lambdalabs/jobs/__init__.py +0 -0
  141. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/lambdalabs/jobs/builders.py +0 -0
  142. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/lambdalabs/preflight.py +0 -0
  143. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/lambdalabs/pricing.py +0 -0
  144. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/preflight.py +0 -0
  145. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/realized.py +0 -0
  146. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/runpod/__init__.py +0 -0
  147. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/runpod/api.py +0 -0
  148. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/runpod/auth.py +0 -0
  149. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/runpod/cost.py +0 -0
  150. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/runpod/gpus.py +0 -0
  151. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/runpod/jobs.py +0 -0
  152. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/runpod/keys.py +0 -0
  153. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/runpod/preflight.py +0 -0
  154. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/runpod/pricing.py +0 -0
  155. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/runpod/slots.py +0 -0
  156. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/runpod/train/__init__.py +0 -0
  157. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/runpod/train/endpoints.py +0 -0
  158. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/vast/__init__.py +0 -0
  159. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/vast/api.py +0 -0
  160. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/vast/auth.py +0 -0
  161. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/vast/jobs/__init__.py +0 -0
  162. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/vast/jobs/builders.py +0 -0
  163. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/vast/preflight.py +0 -0
  164. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/vast/pricing.py +0 -0
  165. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/providers/weight_cache_preload.py +0 -0
  166. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/py.typed +0 -0
  167. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/runner/__init__.py +0 -0
  168. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/runner/checkpoints.py +0 -0
  169. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/runner/deploy.py +0 -0
  170. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/runner/lifecycle.py +0 -0
  171. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/runner/verified_revisions.py +0 -0
  172. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/schema/__init__.py +0 -0
  173. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/schema/fields.py +0 -0
  174. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/serve/__init__.py +0 -0
  175. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/serve/deploy.py +0 -0
  176. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/serve/export.py +0 -0
  177. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/serve/preflight.py +0 -0
  178. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/serve/pricing.py +0 -0
  179. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/serve/urls.py +0 -0
  180. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/server/__init__.py +0 -0
  181. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/server/__main__.py +0 -0
  182. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/server/_deps.py +0 -0
  183. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/server/_internal_client.py +0 -0
  184. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/server/_locks.py +0 -0
  185. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/server/_runtime.py +0 -0
  186. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/server/app.py +0 -0
  187. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/server/auth.py +0 -0
  188. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/server/billing.py +0 -0
  189. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/server/billing_retry.py +0 -0
  190. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/server/checkpoints.py +0 -0
  191. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/server/db.py +0 -0
  192. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/server/environment_registry.py +0 -0
  193. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/server/envs.py +0 -0
  194. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/server/reconcile.py +0 -0
  195. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/server/repo_cleanup.py +0 -0
  196. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/server/routes/__init__.py +0 -0
  197. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/server/routes/envs.py +0 -0
  198. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/server/routes/meta.py +0 -0
  199. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/server/routes/runs.py +0 -0
  200. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/server/routes/serving.py +0 -0
  201. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/server/run_registry.py +0 -0
  202. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/flash/spec.py +0 -0
  203. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/infisical-entrypoint.sh +0 -0
  204. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/scripts/build_dev_dist.py +0 -0
  205. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/__init__.py +0 -0
  206. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/_helpers/__init__.py +0 -0
  207. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/_helpers/runner.py +0 -0
  208. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/_helpers/specs.py +0 -0
  209. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/_helpers/vast.py +0 -0
  210. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/conftest.py +0 -0
  211. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/fixtures/math_eval.jsonl +0 -0
  212. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/fixtures/math_train.jsonl +0 -0
  213. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/live/__init__.py +0 -0
  214. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/live/conftest.py +0 -0
  215. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/live/test_lambda_live.py +0 -0
  216. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/live/test_runpod_live.py +0 -0
  217. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/live/test_vast_live.py +0 -0
  218. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_accounting_coverage.py +0 -0
  219. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_agent_flash_cli_contract.py +0 -0
  220. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_algorithms.py +0 -0
  221. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_allocator.py +0 -0
  222. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_async_uploads.py +0 -0
  223. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_b200_rollout_opt.py +0 -0
  224. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_backend_jobspec_contract.py +0 -0
  225. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_base_model_provenance.py +0 -0
  226. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_billing_retry.py +0 -0
  227. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_cancel_remote.py +0 -0
  228. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_catalog_consistency.py +0 -0
  229. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_chalk_kernels.py +0 -0
  230. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_charge_pricing.py +0 -0
  231. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_checkpoints.py +0 -0
  232. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_cli_commands.py +0 -0
  233. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_cli_commands_coverage.py +0 -0
  234. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_cli_errors.py +0 -0
  235. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_cli_estimate.py +0 -0
  236. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_cli_help.py +0 -0
  237. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_cli_main_coverage.py +0 -0
  238. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_cli_managed.py +0 -0
  239. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_cli_render_coverage.py +0 -0
  240. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_cli_render_theme.py +0 -0
  241. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_cli_traces.py +0 -0
  242. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_client.py +0 -0
  243. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_client_server_integration.py +0 -0
  244. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_client_stream_reads.py +0 -0
  245. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_config_overrides.py +0 -0
  246. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_controlled_experiment_repairs.py +0 -0
  247. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_cost_analytical.py +0 -0
  248. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_cost_equation.py +0 -0
  249. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_cost_estimate.py +0 -0
  250. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_cost_hardware.py +0 -0
  251. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_cost_models.py +0 -0
  252. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_cost_rewards.py +0 -0
  253. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_deploy_latency.py +0 -0
  254. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_dev_channel.py +0 -0
  255. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_disk_gb.py +0 -0
  256. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_endpoint_name.py +0 -0
  257. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_env_cache_evict.py +0 -0
  258. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_env_delete.py +0 -0
  259. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_env_download.py +0 -0
  260. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_env_download_api.py +0 -0
  261. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_env_no_install.py +0 -0
  262. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_env_publish.py +0 -0
  263. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_env_pull.py +0 -0
  264. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_env_pull_coverage.py +0 -0
  265. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_env_pull_loader_coverage.py +0 -0
  266. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_env_pull_managed_control_plane.py +0 -0
  267. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_env_push.py +0 -0
  268. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_env_rate_limit_resolve.py +0 -0
  269. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_env_test.py +0 -0
  270. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_envs_coverage.py +0 -0
  271. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_export.py +0 -0
  272. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_flash_mvp.py +0 -0
  273. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_flash_worker.py +0 -0
  274. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_flashinfer_cache_dirs.py +0 -0
  275. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_github_urlopen_retry.py +0 -0
  276. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_gpu_type_single_field.py +0 -0
  277. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_gpus.py +0 -0
  278. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_grpo_cudagraphs.py +0 -0
  279. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_grpo_mask_aware.py +0 -0
  280. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_grpo_params.py +0 -0
  281. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_grpo_perturn.py +0 -0
  282. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_grpo_sleep_gate.py +0 -0
  283. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_health_liveness.py +0 -0
  284. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_hf_retry.py +0 -0
  285. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_idle_endpoint_reaper.py +0 -0
  286. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_instance_bootstrap_coverage.py +0 -0
  287. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_internal_client.py +0 -0
  288. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_jobs.py +0 -0
  289. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_kernel_cache.py +0 -0
  290. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_kernel_fingerprint.py +0 -0
  291. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_kv_util.py +0 -0
  292. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_lambda_api_coverage.py +0 -0
  293. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_lambda_runner.py +0 -0
  294. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_logging.py +0 -0
  295. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_login_perms.py +0 -0
  296. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_lora_rank_coverage.py +0 -0
  297. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_lora_rank_preflight.py +0 -0
  298. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_managed_config_fields.py +0 -0
  299. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_managed_hf_repo.py +0 -0
  300. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_metrics_schema_agent_contract.py +0 -0
  301. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_mig_guard.py +0 -0
  302. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_multi_gpu_gate.py +0 -0
  303. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_multimodal_input_grads.py +0 -0
  304. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_multimodal_training.py +0 -0
  305. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_multiturn_image_rollout.py +0 -0
  306. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_multiturn_per_turn_reward.py +0 -0
  307. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_multiturn_rollout.py +0 -0
  308. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_multiturn_rollout_coverage.py +0 -0
  309. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_multiturn_rollout_records.py +0 -0
  310. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_multiturn_rollout_request_policy.py +0 -0
  311. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_named_reward_metrics.py +0 -0
  312. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_oom_escalate_gpu.py +0 -0
  313. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_opd.py +0 -0
  314. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_opd_full_state_resume.py +0 -0
  315. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_opd_resume_safety.py +0 -0
  316. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_opd_vllm.py +0 -0
  317. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_open_model_policy.py +0 -0
  318. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_orchestrator_flash.py +0 -0
  319. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_packing.py +0 -0
  320. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_packing_coverage.py +0 -0
  321. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_poll_helpers.py +0 -0
  322. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_preflight.py +0 -0
  323. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_provider_preflight_coverage.py +0 -0
  324. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_provider_routing.py +0 -0
  325. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_provider_teardown_robustness.py +0 -0
  326. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_providers_symmetry.py +0 -0
  327. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_realized_cost.py +0 -0
  328. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_repo_cleanup.py +0 -0
  329. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_resolve_params_b.py +0 -0
  330. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_resume_on_retry.py +0 -0
  331. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_rollout_samples.py +0 -0
  332. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_runmgmt.py +0 -0
  333. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_runpod_api_delete.py +0 -0
  334. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_runpod_key_fingerprint.py +0 -0
  335. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_runpod_key_waterfall.py +0 -0
  336. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_runpod_slots.py +0 -0
  337. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_serve.py +0 -0
  338. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_server_api.py +0 -0
  339. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_server_app_coverage.py +0 -0
  340. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_server_auth_singleflight.py +0 -0
  341. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_server_billing.py +0 -0
  342. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_server_checkpoints_coverage.py +0 -0
  343. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_server_db.py +0 -0
  344. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_server_envs_coverage.py +0 -0
  345. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_server_locks_coverage.py +0 -0
  346. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_serving_context_preflight.py +0 -0
  347. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_serving_contract.py +0 -0
  348. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_serving_pricing_coverage.py +0 -0
  349. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_serving_schema_coverage.py +0 -0
  350. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_sft_activation_shaping.py +0 -0
  351. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_sft_chunked_nll.py +0 -0
  352. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_sft_example_selection.py +0 -0
  353. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_sft_gc_off.py +0 -0
  354. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_sft_max_context.py +0 -0
  355. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_sft_tokenize_cache.py +0 -0
  356. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_sft_verl.py +0 -0
  357. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_single_turn_multimodal_grpo.py +0 -0
  358. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_spec_and_validation.py +0 -0
  359. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_structured_outputs.py +0 -0
  360. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_thinking_config.py +0 -0
  361. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_train_context_preflight.py +0 -0
  362. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_training_controls.py +0 -0
  363. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_update_check.py +0 -0
  364. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_vast_api.py +0 -0
  365. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_vast_api_coverage.py +0 -0
  366. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_vast_offers.py +0 -0
  367. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_vast_provider_coverage.py +0 -0
  368. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_vast_runner.py +0 -0
  369. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_verified_revisions.py +0 -0
  370. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_verifiers.py +0 -0
  371. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_verl_common.py +0 -0
  372. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_version.py +0 -0
  373. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_vl_warmstart_adapter_keys.py +0 -0
  374. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_vram_architecture.py +0 -0
  375. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_wandb_log_coverage.py +0 -0
  376. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_wandb_naming.py +0 -0
  377. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_warmstart_adapter_download.py +0 -0
  378. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_warmstart_cross_repo.py +0 -0
  379. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_weight_cache.py +0 -0
  380. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_worker_dryrun.py +0 -0
  381. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_worker_hardexit.py +0 -0
  382. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_worker_image.py +0 -0
  383. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_worker_init_heartbeat.py +0 -0
  384. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_worker_stack.py +0 -0
  385. {freesolo_flash_dev-1.0.26 → freesolo_flash_dev-1.0.28}/tests/test_worker_thinking.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: freesolo-flash-dev
3
- Version: 1.0.26
3
+ Version: 1.0.28
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
@@ -1437,12 +1437,22 @@ def build_opd_verl_overrides(config: dict) -> list[str]:
1437
1437
  "data.truncation=error",
1438
1438
  "data.shuffle=false",
1439
1439
  f"data.seed={_hydra_val(config.get('seed', 42))}",
1440
- f"actor_rollout_ref.rollout.seed={_hydra_val(config.get('seed', 42))}",
1440
+ # rollout engine seed. NOT `rollout.seed`: verl 0.8.0's RolloutConfig declares no such field,
1441
+ # so a bare key fails hydra composition and a `+`/`++` prefix composes but then dies in
1442
+ # omega_conf_to_dataclass with an unexpected-kwarg TypeError. engine_kwargs is a declared
1443
+ # dict on both 0.8.0 and 0.9.x and is spread into the vllm engine args *after* verl's own
1444
+ # "seed" entry, so it wins. `++` because the sub-key is absent from the composed node.
1445
+ # per-request sampling is seeded separately by the plugin's deterministic_rollout_seed.
1446
+ f"++actor_rollout_ref.rollout.engine_kwargs.vllm.seed={_hydra_val(config.get('seed', 42))}",
1441
1447
  "data.dataloader_num_workers=0",
1442
1448
  "data.image_key=images",
1443
1449
  "data.return_raw_chat=true",
1444
1450
  "data.return_multi_modal_inputs=false",
1445
- "data.apply_chat_template_kwargs={enable_thinking:" + _hydra_val(config.get("thinking", False)) + "}",
1451
+ # `++`, not a bare key: data.apply_chat_template_kwargs exists but holds an empty struct
1452
+ # dict, so assigning a whole dict to it is rejected as an unknown sub-key.
1453
+ "++data.apply_chat_template_kwargs={enable_thinking:"
1454
+ + _hydra_val(config.get("thinking", False))
1455
+ + "}",
1446
1456
  f"actor_rollout_ref.model.path={_hydra_val(config['model_path'])}",
1447
1457
  "actor_rollout_ref.model.trust_remote_code=true",
1448
1458
  "actor_rollout_ref.model.use_remove_padding=true",
@@ -1473,7 +1483,9 @@ def build_opd_verl_overrides(config: dict) -> list[str]:
1473
1483
  "actor_rollout_ref.rollout.mode=async",
1474
1484
  f"actor_rollout_ref.rollout.tensor_model_parallel_size={_hydra_val(config['n_gpus_per_node'])}",
1475
1485
  f"actor_rollout_ref.rollout.n={_hydra_val(config['group_size'])}",
1476
- "actor_rollout_ref.rollout.limit_images=8",
1486
+ # `++`, not a bare key: limit_images is a real RolloutConfig field but is absent from the
1487
+ # composed rollout node, so hydra rejects a bare assignment.
1488
+ "++actor_rollout_ref.rollout.limit_images=8",
1477
1489
  f"actor_rollout_ref.rollout.max_model_len={_hydra_val(config.get('max_model_len', 32768))}",
1478
1490
  f"actor_rollout_ref.rollout.temperature={_hydra_val(config.get('temperature', 1.0))}",
1479
1491
  f"actor_rollout_ref.rollout.top_p={_hydra_val(config.get('top_p', 1.0))}",
@@ -16,6 +16,7 @@ from __future__ import annotations
16
16
 
17
17
  import contextlib
18
18
  import json
19
+ import math
19
20
  import os
20
21
  import random
21
22
  import re
@@ -39,6 +40,21 @@ DATA_SOURCE = "flash_env"
39
40
  # --------------------------------------------------------------------------------------------
40
41
  # pure helpers (no verl, no gpu, no network) -- unit tested directly.
41
42
  # --------------------------------------------------------------------------------------------
43
+ def _verl_epochs_for_horizon(
44
+ *, epochs: int, prompt_count: int, prompts_per_step: int, steps: int
45
+ ) -> int:
46
+ if prompt_count <= 0:
47
+ raise ValueError("prompt_count must be positive")
48
+ if prompts_per_step <= 0:
49
+ raise ValueError("prompts_per_step must be positive")
50
+ if prompt_count < prompts_per_step:
51
+ raise ValueError("prompt_count must be at least prompts_per_step")
52
+ # verl hardcodes drop_last=True, so each epoch serves floor(prompt_count / batch_size) steps.
53
+ # the flag cannot be configured off, and ceil here would still under-serve the requested horizon.
54
+ steps_per_epoch = prompt_count // prompts_per_step
55
+ return max(epochs, math.ceil(steps / steps_per_epoch))
56
+
57
+
42
58
  def build_verl_dataset_rows(
43
59
  message_prompts: list[list[dict]],
44
60
  example_indices: list[int],
@@ -70,8 +86,9 @@ def build_verl_overrides(cfg: dict) -> list[str]:
70
86
  """build the hydra override list for `python -m verl.trainer.main_ppo` (grpo + lora + vllm).
71
87
 
72
88
  carries the flash grpo recipe: dr-grpo advantages (no std norm, constant-length loss), the
73
- job's kl coefficient (flash default 0 = no kl term), constant lr, seed, sampling top_p,
74
- num_iterations (ppo_epochs), the max-steps horizon, and the save schedule.
89
+ job's kl coefficient (flash default 0 = no kl term), constant lr, seed, sampling top_p, and one
90
+ ppo epoch so total_training_steps counts optimizer updates. unlike trl's generation-batch reuse,
91
+ verl samples a fresh rollout per update, so rollout volume and policy staleness still differ.
75
92
  """
76
93
  kl_on = float(cfg["kl_coef"]) > 0
77
94
  o = [
@@ -97,7 +114,13 @@ def build_verl_overrides(cfg: dict) -> list[str]:
97
114
  # thread flash's thinking mode so the rollout sees the same prompt as the trl path.
98
115
  f"+data.apply_chat_template_kwargs.enable_thinking={str(bool(cfg.get('thinking', False))).lower()}",
99
116
  f"data.seed={cfg['seed']}",
100
- f"actor_rollout_ref.rollout.seed={cfg['seed']}",
117
+ # rollout sampling seed. NOT `rollout.seed`: verl 0.8.0's RolloutConfig declares no such
118
+ # field, so a bare key fails hydra composition and a `+`/`++` prefix composes but then dies
119
+ # in omega_conf_to_dataclass with an unexpected-kwarg TypeError. engine_kwargs is a declared
120
+ # dict on both 0.8.0 and 0.9.x and is spread into the vllm engine args *after* verl's own
121
+ # "seed" entry, so it wins. `++` because the sub-key is absent from the composed node.
122
+ # single replica here (tp == n_gpus, nnodes=1), so verl's replica_rank offset is always 0.
123
+ f"++actor_rollout_ref.rollout.engine_kwargs.vllm.seed={cfg['seed']}",
101
124
  f"actor_rollout_ref.model.path={cfg['model_id']}",
102
125
  f"actor_rollout_ref.model.lora_rank={cfg['lora_rank']}",
103
126
  f"actor_rollout_ref.model.lora_alpha={cfg['lora_alpha']}",
@@ -116,12 +139,15 @@ def build_verl_overrides(cfg: dict) -> list[str]:
116
139
  else []
117
140
  ),
118
141
  f"actor_rollout_ref.actor.optim.lr={cfg['lr']}",
142
+ # only the lora adapter is trainable; decaying its weights toward zero is not part of grpo.
143
+ "actor_rollout_ref.actor.optim.weight_decay=0.0",
119
144
  # 0 warmup -> verl's warmup+constant scheduler holds lr flat, matching the trl constant recipe.
120
145
  "actor_rollout_ref.actor.optim.lr_warmup_steps_ratio=0.0",
121
146
  f"actor_rollout_ref.actor.ppo_mini_batch_size={cfg['prompts_per_step']}",
122
147
  f"actor_rollout_ref.actor.ppo_micro_batch_size_per_gpu={cfg['micro_batch']}",
123
- # num_iterations: amortize each generation batch over N optimizer passes.
124
- f"actor_rollout_ref.actor.ppo_epochs={cfg['num_iterations']}",
148
+ # ppo_epochs multiplies verl's update loop, so its default of 1 preserves the requested update
149
+ # count and on-policy baseline. unlike trl reuse, verl samples a fresh rollout for every update.
150
+ f"actor_rollout_ref.actor.ppo_epochs={cfg['ppo_epochs']}",
125
151
  "actor_rollout_ref.rollout.name=vllm",
126
152
  f"actor_rollout_ref.rollout.n={cfg['group_size']}",
127
153
  # safetensors load format is required for lora rollout on vllm.
@@ -170,6 +196,82 @@ def build_verl_overrides(cfg: dict) -> list[str]:
170
196
  return o
171
197
 
172
198
 
199
+ def _build_verl_training_cfg(
200
+ inp: dict,
201
+ *,
202
+ train_files: str,
203
+ val_files: str,
204
+ model_id: str,
205
+ micro_batch: int,
206
+ thinking: bool,
207
+ loggers: str,
208
+ fp8_kv: bool,
209
+ reward_path: str,
210
+ local_dir: str,
211
+ ) -> dict:
212
+ return {
213
+ "train_files": train_files,
214
+ "val_files": val_files,
215
+ "model_id": model_id,
216
+ "lora_rank": inp["lora_rank"],
217
+ "lora_alpha": inp["lora_alpha"],
218
+ "target_modules": "all-linear",
219
+ "lr": inp["lr"],
220
+ "group_size": inp["group_size"],
221
+ "prompts_per_step": inp["prompts_per_step"],
222
+ "micro_batch": micro_batch,
223
+ "max_prompt_len": inp["max_prompt_len"],
224
+ "max_completion": inp["max_completion"],
225
+ "temperature": inp["temperature"],
226
+ "top_p": inp["top_p"],
227
+ "kl_coef": inp["kl_coef"],
228
+ "thinking": thinking,
229
+ "loss_agg_mode": "seq-mean-token-sum-norm",
230
+ "seed": inp["seed"],
231
+ "ppo_epochs": inp["ppo_epochs"],
232
+ "steps": int(inp["steps"]),
233
+ "warmstart_adapter": inp["warmstart_adapter"],
234
+ "gpu_mem_util": 0.5,
235
+ "tp_size": 1,
236
+ "loggers": loggers,
237
+ "fp8_kv": fp8_kv,
238
+ "reward_path": reward_path,
239
+ "reward_name": "compute_score",
240
+ "total_epochs": inp["verl_total_epochs"],
241
+ "save_freq": inp["save_every"],
242
+ "local_dir": local_dir,
243
+ }
244
+
245
+
246
+ def _build_verl_train_notes(
247
+ inp: dict,
248
+ *,
249
+ steps_run: int,
250
+ retained_prompts: int,
251
+ reward_history: list[float],
252
+ loss_curve: list[float],
253
+ ) -> dict:
254
+ return {
255
+ "backend": "verl",
256
+ "steps": steps_run,
257
+ "epochs": inp["epochs"],
258
+ "retained_prompts": retained_prompts,
259
+ "group_size": inp["group_size"],
260
+ "reward_history": reward_history,
261
+ "loss_curve": loss_curve,
262
+ "grpo_recipe": {
263
+ "kl_coef": inp["kl_coef"],
264
+ "temperature": inp["temperature"],
265
+ "top_p": inp["top_p"],
266
+ "ppo_epochs": inp["ppo_epochs"],
267
+ "verl_total_epochs": inp["verl_total_epochs"],
268
+ "seed": inp["seed"],
269
+ "loss_agg_mode": "seq-mean-token-sum-norm",
270
+ "norm_adv_by_std_in_grpo": False,
271
+ },
272
+ }
273
+
274
+
173
275
  def render_reward_module(url_env: str = "FLASH_VERL_REWARD_URL") -> str:
174
276
  """source for the verl custom reward module.
175
277
 
@@ -490,10 +592,11 @@ def _resolve_single_turn_inputs():
490
592
  flush=True,
491
593
  )
492
594
  # trl drops truncated (non-eos) completions from the grpo loss (mask_truncated_completions,
493
- # default True); verl's vllm rollout here has no per-completion truncation-mask knob, so verl
494
- # keeps them. stop_sequences (the only case that turns masking off) already fails loudly above,
495
- # so this is always the default-True case. record the divergence for parity observability
496
- # rather than silently ignoring it; adding verl-side masking is a tracked follow-up.
595
+ # default True); verl 0.8.0 cannot express this through config. its vllm server discards the
596
+ # finish_reason length/stop distinction, and its rollout schemas and trainer masks never apply
597
+ # finish-reason-dependent response-loss masking anyway. stop_sequences (the only case that turns
598
+ # masking off) already fails loudly above, so this is always the default-True case. a real fix needs
599
+ # finish-reason propagation plus explicit zeroing of the truncated response loss mask.
497
600
  if _w.grpo_mask_truncated_completions(_t):
498
601
  print(
499
602
  "[rl-verl] mask_truncated_completions=True; verl keeps truncated completions in the "
@@ -587,16 +690,15 @@ def _resolve_single_turn_inputs():
587
690
  epochs=epochs, prompt_count=len(prompts), prompts_per_step=prompts_per_step
588
691
  )
589
692
  steps = resolve_update_horizon(derived_steps, getattr(_t, "max_steps", None) if _t else None)
590
- # verl stops at BOTH total_epochs and total_training_steps; when an explicit max_steps exceeds
591
- # the epoch-derived count, raise epochs so the dataloader can actually serve the horizon
592
- # (otherwise verl exits early at total_epochs and the run under-trains).
593
- if int(steps) > int(derived_steps) and len(prompts) > 0:
594
- import math as _math
595
-
596
- # verl's dataloader drops the last partial batch: floor, not ceil, else the bumped
597
- # epoch count still under-serves the requested horizon.
598
- steps_per_epoch = max(1, len(prompts) // prompts_per_step)
599
- epochs = max(epochs, _math.ceil(int(steps) / steps_per_epoch))
693
+ # verl stops at both total_epochs and total_training_steps. give its hardcoded drop_last
694
+ # dataloader enough epoch capacity to serve the horizon, but preserve the configured epoch count
695
+ # for user-facing metadata. total_training_steps prevents the capacity headroom from over-training.
696
+ verl_total_epochs = _verl_epochs_for_horizon(
697
+ epochs=epochs,
698
+ prompt_count=len(prompts),
699
+ prompts_per_step=prompts_per_step,
700
+ steps=int(steps),
701
+ )
600
702
  save_every = int(_t.save_every) if (_t and _t.save_every) else 20
601
703
 
602
704
  return {
@@ -619,10 +721,12 @@ def _resolve_single_turn_inputs():
619
721
  "lora_alpha": lora_alpha,
620
722
  "warmstart_adapter": warmstart_adapter,
621
723
  "epochs": epochs,
724
+ "verl_total_epochs": verl_total_epochs,
622
725
  "steps": int(steps),
623
726
  "save_every": save_every,
624
- # flash amortizes each generation batch over 2 optimizer passes (num_iterations=2).
625
- "num_iterations": 2,
727
+ # verl's default preserves the update horizon and on-policy baseline; unlike trl reuse, each
728
+ # update gets a fresh rollout batch.
729
+ "ppo_epochs": 1,
626
730
  "seed": int(backend_seed(_w.SEED)),
627
731
  }
628
732
 
@@ -736,22 +840,18 @@ def run_rl_verl():
736
840
  )
737
841
  except Exception: # no cuda / probe failure -> conservative bf16 kv
738
842
  fp8_kv = False
739
- cfg = {
740
- "train_files": train_pq, "val_files": val_pq,
741
- "model_id": model_path_for_verl, "lora_rank": inp["lora_rank"],
742
- "lora_alpha": inp["lora_alpha"], "target_modules": "all-linear",
743
- "lr": inp["lr"], "group_size": inp["group_size"],
744
- "prompts_per_step": inp["prompts_per_step"], "micro_batch": micro_batch,
745
- "max_prompt_len": inp["max_prompt_len"], "max_completion": inp["max_completion"],
746
- "temperature": inp["temperature"], "top_p": inp["top_p"], "kl_coef": inp["kl_coef"],
747
- "thinking": bool(_w.THINKING),
748
- "loss_agg_mode": "seq-mean-token-sum-norm", "seed": inp["seed"],
749
- "num_iterations": inp["num_iterations"], "steps": expected_steps,
750
- "warmstart_adapter": inp["warmstart_adapter"],
751
- "gpu_mem_util": 0.5, "tp_size": 1, "loggers": loggers, "fp8_kv": fp8_kv,
752
- "reward_path": reward_py, "reward_name": "compute_score",
753
- "total_epochs": inp["epochs"], "save_freq": inp["save_every"], "local_dir": local_dir,
754
- }
843
+ cfg = _build_verl_training_cfg(
844
+ inp,
845
+ train_files=train_pq,
846
+ val_files=val_pq,
847
+ model_id=model_path_for_verl,
848
+ micro_batch=micro_batch,
849
+ thinking=bool(_w.THINKING),
850
+ loggers=loggers,
851
+ fp8_kv=fp8_kv,
852
+ reward_path=reward_py,
853
+ local_dir=local_dir,
854
+ )
755
855
  overrides = build_verl_overrides(cfg)
756
856
 
757
857
  setup_seconds = time.time() - t_start
@@ -867,22 +967,11 @@ def run_rl_verl():
867
967
  )
868
968
  if resp_len_history
869
969
  else 0,
870
- notes={
871
- "backend": "verl",
872
- "steps": steps_run,
873
- "epochs": inp["epochs"],
874
- "retained_prompts": len(prompts),
875
- "group_size": inp["group_size"],
876
- "reward_history": reward_history,
877
- "loss_curve": loss_curve,
878
- "grpo_recipe": {
879
- "kl_coef": inp["kl_coef"],
880
- "temperature": inp["temperature"],
881
- "top_p": inp["top_p"],
882
- "num_iterations": inp["num_iterations"],
883
- "seed": inp["seed"],
884
- "loss_agg_mode": "seq-mean-token-sum-norm",
885
- "norm_adv_by_std_in_grpo": False,
886
- },
887
- },
970
+ notes=_build_verl_train_notes(
971
+ inp,
972
+ steps_run=steps_run,
973
+ retained_prompts=len(prompts),
974
+ reward_history=reward_history,
975
+ loss_curve=loss_curve,
976
+ ),
888
977
  )
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "freesolo-flash-dev"
3
- version = "1.0.26"
3
+ version = "1.0.28"
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).
@@ -116,7 +116,7 @@ artifacts = ["flash/py.typed"]
116
116
  # auto-published by .github/workflows/publish-dev.yml: a push to `dev` whose version isn't yet on
117
117
  # PyPI publishes it; pushes that don't change it find it already published and no-op. So cutting a
118
118
  # dev-channel release = bump this (and [project].version) and merge to `dev`.
119
- version = "1.0.26"
119
+ version = "1.0.28"
120
120
 
121
121
  [tool.pytest.ini_options]
122
122
  pythonpath = ["."]
@@ -4389,7 +4389,11 @@ def test_overrides_match_verl_0_8_sync_distillation_contract():
4389
4389
  assert overrides["data.image_key"] == "images"
4390
4390
  assert overrides["data.return_raw_chat"] == "true"
4391
4391
  assert overrides["data.return_multi_modal_inputs"] == "false"
4392
- assert overrides["actor_rollout_ref.rollout.limit_images"] == "8"
4392
+ # `++`-prefixed: these keys are absent from the composed node, so a bare assignment would abort
4393
+ # the run at hydra composition. see build_opd_verl_overrides for the per-key reasoning.
4394
+ assert overrides["++actor_rollout_ref.rollout.limit_images"] == "8"
4395
+ assert overrides["++actor_rollout_ref.rollout.engine_kwargs.vllm.seed"] == "42"
4396
+ assert "actor_rollout_ref.rollout.seed" not in overrides
4393
4397
  assert "actor.engine.ulysses_sequence_parallel_size" not in overrides
4394
4398
  assert "ref_log_prob" not in " ".join(overrides)
4395
4399
  assert not any("structured_outputs_config" in key for key in overrides)
@@ -60,7 +60,7 @@ def _overrides_cfg(**over):
60
60
  "target_modules": "all-linear", "lr": 1e-5, "group_size": 8,
61
61
  "prompts_per_step": 16, "micro_batch": 2, "max_prompt_len": 2048,
62
62
  "max_completion": 320, "temperature": 1.0, "top_p": 0.95, "kl_coef": 0.0,
63
- "loss_agg_mode": "seq-mean-token-sum-norm", "seed": 42, "num_iterations": 2,
63
+ "loss_agg_mode": "seq-mean-token-sum-norm", "seed": 42, "ppo_epochs": 1,
64
64
  "steps": 60, "gpu_mem_util": 0.5, "tp_size": 1, "loggers": "console", "fp8_kv": False,
65
65
  "warmstart_adapter": "", "reward_path": "/w/reward.py", "reward_name": "compute_score",
66
66
  "total_epochs": 1, "save_freq": 20, "local_dir": "/w/ckpt",
@@ -79,12 +79,16 @@ def test_build_verl_overrides_carries_dr_grpo_recipe():
79
79
  assert "actor_rollout_ref.rollout.n=8" in o
80
80
  assert "actor_rollout_ref.rollout.load_format=safetensors" in o
81
81
  assert "actor_rollout_ref.rollout.top_p=0.95" in o
82
- # constant lr, num_iterations, gradient checkpointing, seed, max-steps horizon, save schedule.
82
+ # constant lr, on-policy updates, gradient checkpointing, seed, max-steps horizon, save schedule.
83
+ assert "actor_rollout_ref.actor.optim.weight_decay=0.0" in o
83
84
  assert "actor_rollout_ref.actor.optim.lr_warmup_steps_ratio=0.0" in o
84
- assert "actor_rollout_ref.actor.ppo_epochs=2" in o
85
+ assert "actor_rollout_ref.actor.ppo_epochs=1" in o
85
86
  assert "actor_rollout_ref.model.enable_gradient_checkpointing=True" in o
86
87
  assert "data.seed=42" in o
87
- assert "actor_rollout_ref.rollout.seed=42" in o
88
+ # the rollout engine seed rides engine_kwargs, not `rollout.seed`, which verl 0.8.0's
89
+ # RolloutConfig does not declare. see build_verl_overrides for the full reasoning.
90
+ assert "++actor_rollout_ref.rollout.engine_kwargs.vllm.seed=42" in o
91
+ assert "actor_rollout_ref.rollout.seed=42" not in o
88
92
  assert "trainer.total_training_steps=60" in o
89
93
  assert "trainer.save_freq=20" in o
90
94
  assert "trainer.max_actor_ckpt_to_keep=1" in o
@@ -95,6 +99,141 @@ def test_build_verl_overrides_carries_dr_grpo_recipe():
95
99
  assert "algorithm.rollout_correction.rollout_is_threshold=2.0" in o
96
100
 
97
101
 
102
+ def test_build_verl_overrides_does_not_emit_inert_drop_last_override():
103
+ # this guards only against flash emitting a misleading no-op; it does not prove verl reads the key.
104
+ o = rl_verl.build_verl_overrides(_overrides_cfg())
105
+ assert not any("drop_last" in override for override in o)
106
+
107
+
108
+ @pytest.mark.parametrize(
109
+ ("prompt_count", "prompts_per_step", "epochs", "max_steps", "expected_steps", "expected_epochs"),
110
+ [
111
+ pytest.param(33, 16, 2, None, 5, 3, id="partial-batch-derived-horizon"),
112
+ pytest.param(32, 16, 2, 7, 7, 4, id="explicit-horizon-beyond-derived"),
113
+ pytest.param(32, 16, 2, None, 4, 2, id="exactly-divisible"),
114
+ ],
115
+ )
116
+ def test_verl_epoch_capacity_reaches_update_horizon(
117
+ prompt_count, prompts_per_step, epochs, max_steps, expected_steps, expected_epochs
118
+ ):
119
+ derived_steps = rl_verl.on_policy_steps(
120
+ epochs=epochs, prompt_count=prompt_count, prompts_per_step=prompts_per_step
121
+ )
122
+ steps = rl_verl.resolve_update_horizon(derived_steps, max_steps)
123
+ resolved_epochs = rl_verl._verl_epochs_for_horizon(
124
+ epochs=epochs,
125
+ prompt_count=prompt_count,
126
+ prompts_per_step=prompts_per_step,
127
+ steps=steps,
128
+ )
129
+
130
+ assert steps == expected_steps
131
+ assert resolved_epochs == expected_epochs
132
+ assert (prompt_count // prompts_per_step) * resolved_epochs >= steps
133
+
134
+
135
+ @pytest.mark.parametrize(
136
+ ("prompt_count", "prompts_per_step", "message"),
137
+ [
138
+ pytest.param(0, 16, "prompt_count must be positive", id="no-prompts"),
139
+ pytest.param(5, 0, "prompts_per_step must be positive", id="zero-batch"),
140
+ pytest.param(5, 16, "prompt_count must be at least", id="batch-exceeds-prompts"),
141
+ ],
142
+ )
143
+ def test_verl_epoch_capacity_rejects_invalid_batch_inputs(
144
+ prompt_count, prompts_per_step, message
145
+ ):
146
+ with pytest.raises(ValueError, match=message):
147
+ rl_verl._verl_epochs_for_horizon(
148
+ epochs=2,
149
+ prompt_count=prompt_count,
150
+ prompts_per_step=prompts_per_step,
151
+ steps=3,
152
+ )
153
+
154
+
155
+ def test_verl_epoch_capacity_invariant_across_valid_inputs():
156
+ for prompt_count in range(1, 34):
157
+ for prompts_per_step in range(1, prompt_count + 1):
158
+ for epochs in (1, 2, 4):
159
+ for steps in (1, epochs, epochs + 5):
160
+ resolved_epochs = rl_verl._verl_epochs_for_horizon(
161
+ epochs=epochs,
162
+ prompt_count=prompt_count,
163
+ prompts_per_step=prompts_per_step,
164
+ steps=steps,
165
+ )
166
+ assert (prompt_count // prompts_per_step) * resolved_epochs >= steps
167
+
168
+
169
+ def test_verl_resolver_builds_capacity_overrides_and_configured_metadata(monkeypatch):
170
+ from flash.engine.worker._pkg import W
171
+ from flash.spec import JobSpec
172
+
173
+ class _Env:
174
+ multi_turn = False
175
+ is_tool_env = False
176
+
177
+ def dataset(self):
178
+ return [{"index": i} for i in range(33)]
179
+
180
+ def prompt_messages(self, ex):
181
+ return [{"role": "user", "content": f"question {ex['index']}"}]
182
+
183
+ class _Tokenizer:
184
+ pad_token = None
185
+ eos_token = "<eos>"
186
+
187
+ def apply_chat_template(self, messages, **kwargs):
188
+ return messages[0]["content"]
189
+
190
+ def __call__(self, text, **kwargs):
191
+ return SimpleNamespace(input_ids=[1])
192
+
193
+ spec = JobSpec.from_dict(
194
+ {
195
+ "model": "Qwen/Qwen3.5-0.8B",
196
+ "algorithm": "grpo",
197
+ "train": {"batch_size": 16, "epochs": 2},
198
+ }
199
+ )
200
+ monkeypatch.setattr(W, "JOB_SPEC", spec, raising=False)
201
+ monkeypatch.setattr(W, "SEED", 42, raising=False)
202
+ monkeypatch.setattr(W, "THINKING", False, raising=False)
203
+ monkeypatch.setattr(W, "require_active_env", lambda: _Env(), raising=False)
204
+ monkeypatch.setattr(W, "grpo_overrides", lambda: {}, raising=False)
205
+ monkeypatch.setattr(W, "grpo_mask_truncated_completions", lambda train: False, raising=False)
206
+ monkeypatch.setattr(W, "load_tokenizer", lambda *args, **kwargs: _Tokenizer(), raising=False)
207
+ monkeypatch.setattr(rl_verl, "seed_training_rngs", lambda seed: None)
208
+
209
+ inp = rl_verl._resolve_single_turn_inputs()
210
+ cfg = rl_verl._build_verl_training_cfg(
211
+ inp,
212
+ train_files="/w/train.parquet",
213
+ val_files="/w/val.parquet",
214
+ model_id=inp["model_id"],
215
+ micro_batch=1,
216
+ thinking=False,
217
+ loggers="console",
218
+ fp8_kv=False,
219
+ reward_path="/w/reward.py",
220
+ local_dir="/w/ckpt",
221
+ )
222
+ overrides = rl_verl.build_verl_overrides(cfg)
223
+ notes = rl_verl._build_verl_train_notes(
224
+ inp,
225
+ steps_run=5,
226
+ retained_prompts=len(inp["prompts"]),
227
+ reward_history=[],
228
+ loss_curve=[],
229
+ )
230
+
231
+ assert "trainer.total_training_steps=5" in overrides
232
+ assert "trainer.total_epochs=3" in overrides
233
+ assert notes["epochs"] == 2
234
+ assert notes["grpo_recipe"]["verl_total_epochs"] == 3
235
+
236
+
98
237
  def test_build_verl_overrides_wandb_logger_when_enabled():
99
238
  o = rl_verl.build_verl_overrides(_overrides_cfg(loggers="console,wandb"))
100
239
  assert "trainer.logger=[console,wandb]" in o
@@ -1025,7 +1025,7 @@ wheels = [
1025
1025
 
1026
1026
  [[package]]
1027
1027
  name = "freesolo-flash"
1028
- version = "1.0.26"
1028
+ version = "1.0.28"
1029
1029
  source = { editable = "." }
1030
1030
 
1031
1031
  [package.optional-dependencies]