freesolo-flash-dev 1.2.87__tar.gz → 1.2.89__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 (620) hide show
  1. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/PKG-INFO +1 -1
  2. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/adapters/artifacts.py +4 -6
  3. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/adapters/fused_experts.py +62 -32
  4. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/adapters/lora_rank.py +82 -30
  5. freesolo_flash_dev-1.2.89/flash/adapters/targets.py +61 -0
  6. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/commands/__init__.py +7 -14
  7. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/commands/env/push.py +13 -29
  8. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/commands/env/test.py +5 -1
  9. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/commands/train_cost.py +28 -63
  10. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/scaffold/TRAINING.md +14 -2
  11. freesolo_flash_dev-1.2.89/flash/content/image_descriptors.py +363 -0
  12. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/content/multimodal.py +261 -253
  13. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/core/catalog.py +27 -1
  14. freesolo_flash_dev-1.2.89/flash/core/grpo.py +63 -0
  15. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/core/spec.py +128 -72
  16. freesolo_flash_dev-1.2.89/flash/core/spec_persistence.py +109 -0
  17. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cost/analytical.py +1 -4
  18. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cost/facts.py +1 -89
  19. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cost/spec.py +9 -7
  20. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cost/types.py +6 -2
  21. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/plan/model_config_probe.py +3 -5
  22. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/plan/recipe.py +4 -2
  23. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/profiling/image_tokens.py +16 -10
  24. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/profiling/reasoning_render.py +4 -10
  25. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/profiling/tokenizer.py +9 -1
  26. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/__init__.py +42 -11
  27. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/entry/sft.py +2 -2
  28. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/io/heartbeat.py +0 -1
  29. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/io/prefetch.py +3 -6
  30. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/model/adapter.py +31 -8
  31. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/model/lora.py +115 -33
  32. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/opd_train.py +35 -6
  33. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/opd_train_runner.py +113 -7
  34. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/rl_train.py +40 -19
  35. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/rl_train_runner.py +181 -20
  36. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/sft_train.py +27 -5
  37. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/sft_train_runner.py +31 -3
  38. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/teacher/client.py +35 -2
  39. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/core/child/glue.py +455 -30
  40. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/core/child/runtime.py +171 -0
  41. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/opd/batching.py +5 -1
  42. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/opd/bridge.py +131 -106
  43. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/opd/child/bridge.py +167 -2
  44. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/opd/child/multiturn.py +62 -22
  45. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/opd/child/replay_guard.py +12 -0
  46. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/opd/child/runtime.py +3 -0
  47. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/opd/failures.py +11 -1
  48. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/opd/gkd.py +16 -1
  49. freesolo_flash_dev-1.2.89/flash/engine/worker/train/opd/multiturn_media.py +132 -0
  50. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/opd/overrides.py +14 -2
  51. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/opd/prompts.py +28 -8
  52. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/opd/scoring.py +11 -9
  53. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/opd/state.py +3 -0
  54. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/rl/checkpoints.py +8 -1
  55. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/rl/child/multiturn.py +152 -87
  56. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/rl/child/patches.py +253 -24
  57. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/rl/child/plugin.py +27 -0
  58. freesolo_flash_dev-1.2.89/flash/engine/worker/train/rl/identity.py +306 -0
  59. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/rl/inputs.py +27 -13
  60. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/rl/multi_turn.py +324 -88
  61. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/rl/reward_module.py +4 -1
  62. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/rl/verl_config.py +39 -9
  63. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/sft/checkpoints.py +48 -10
  64. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/sft/child/plugin.py +7 -2
  65. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/sft/config.py +1 -0
  66. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/verl/checkpoints.py +374 -5
  67. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/verl/child_io.py +9 -0
  68. freesolo_flash_dev-1.2.89/flash/engine/worker/verl/process_census.py +470 -0
  69. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/envs/adapter.py +3 -0
  70. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/envs/base.py +4 -1
  71. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/envs/identity.py +12 -0
  72. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/envs/loader.py +114 -23
  73. freesolo_flash_dev-1.2.89/flash/envs/staged.py +490 -0
  74. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/_lifecycle/bootstrap.py +16 -15
  75. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/_lifecycle/bootstrap_pip.py +6 -6
  76. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/_lifecycle/poll.py +1 -1
  77. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/_lifecycle/worker.py +9 -6
  78. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/artifacts/weight_cache.py +4 -1
  79. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/realized.py +10 -6
  80. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/runpod/__init__.py +6 -2
  81. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/runpod/api.py +153 -22
  82. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/runpod/jobs.py +1 -6
  83. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/runpod/serverless/endpoints.py +3 -0
  84. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runner/__init__.py +1 -13
  85. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runner/artifacts.py +114 -5
  86. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runner/costs.py +0 -7
  87. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runner/preparation.py +85 -50
  88. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runner/reconciliation.py +118 -9
  89. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runner/status.py +34 -27
  90. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runner/submit.py +17 -21
  91. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runner/supervise/attach.py +39 -11
  92. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runner/supervise/deploy.py +18 -7
  93. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runner/supervise/lifecycle.py +52 -52
  94. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runner/supervise/recovery.py +86 -8
  95. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runner/supervise/seed_submission.py +1 -12
  96. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runner/supervise/transitions.py +0 -3
  97. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/schema/__init__.py +21 -25
  98. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/schema/fields.py +6 -2
  99. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/serve/deploy.py +6 -0
  100. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/serve/export.py +78 -185
  101. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/domain/reconcile.py +8 -10
  102. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/domain/repo_cleanup.py +4 -1
  103. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/domain/teacher_broker.py +20 -15
  104. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/domain/teacher_errors.py +17 -1
  105. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/platform/db.py +20 -26
  106. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/platform/deps.py +4 -6
  107. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/routes/serving.py +14 -47
  108. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/routes/serving_revisions.py +25 -2
  109. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/routes/serving_smoke.py +160 -26
  110. freesolo_flash_dev-1.2.89/flash/teacher/provider_status.py +35 -0
  111. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/teacher/retry_contract.py +8 -27
  112. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/pyproject.toml +2 -2
  113. freesolo_flash_dev-1.2.89/scripts/check_rollout_identity_actor.py +53 -0
  114. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/_helpers/runner.py +1 -0
  115. freesolo_flash_dev-1.2.89/tests/fixtures/qwen35_08b_target_metadata.json +101 -0
  116. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_adapter_shard_completeness.py +7 -5
  117. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_agent_flash_cli_contract.py +0 -29
  118. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_allocator.py +1 -1
  119. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_backend_common.py +30 -7
  120. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_billing_retry.py +2 -94
  121. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_cancel_remote.py +1 -1
  122. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_checkpoints.py +7 -9
  123. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_cli_commands.py +0 -60
  124. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_cli_estimate.py +117 -45
  125. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_cli_render_coverage.py +2 -2
  126. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_controlled_experiment_repairs.py +23 -80
  127. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_cost_analytical.py +0 -16
  128. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_cost_equation.py +2 -10
  129. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_cost_estimate.py +4 -165
  130. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_cost_hardware.py +11 -74
  131. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_dataset_profile.py +87 -1
  132. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_disk_gb.py +30 -6
  133. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_env_evaluations.py +23 -0
  134. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_env_push.py +24 -22
  135. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_env_rate_limit_resolve.py +15 -23
  136. freesolo_flash_dev-1.2.89/tests/test_env_ref_pinning.py +73 -0
  137. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_env_test.py +21 -0
  138. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_export.py +103 -277
  139. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_flash_worker.py +56 -10
  140. freesolo_flash_dev-1.2.89/tests/test_fused_expert_warmstart.py +1894 -0
  141. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_grpo_params.py +1 -1
  142. freesolo_flash_dev-1.2.89/tests/test_grpo_process_census.py +561 -0
  143. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_grpo_reward_batching.py +12 -1
  144. freesolo_flash_dev-1.2.89/tests/test_grpo_rollout_contract.py +458 -0
  145. freesolo_flash_dev-1.2.89/tests/test_grpo_rollout_identity.py +824 -0
  146. freesolo_flash_dev-1.2.89/tests/test_image_environment_capability.py +92 -0
  147. freesolo_flash_dev-1.2.89/tests/test_image_incremental_processor.py +583 -0
  148. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_image_tokens.py +10 -15
  149. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_instance_bootstrap_coverage.py +73 -6
  150. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_jobs.py +201 -4
  151. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_lambda_runner.py +23 -7
  152. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_lora_rank_coverage.py +43 -0
  153. freesolo_flash_dev-1.2.89/tests/test_lora_rank_nested_rung.py +84 -0
  154. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_lora_rank_preflight.py +52 -10
  155. freesolo_flash_dev-1.2.89/tests/test_lora_targeting.py +757 -0
  156. freesolo_flash_dev-1.2.89/tests/test_lora_targeting_pinned_verl.py +240 -0
  157. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_multi_gpu_gate.py +3 -3
  158. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_multimodal_training.py +404 -26
  159. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_oom_escalate_gpu.py +1 -1
  160. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_opd.py +44 -14
  161. freesolo_flash_dev-1.2.89/tests/test_opd_multiturn_failure_exit.py +449 -0
  162. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_opd_replay_guard.py +24 -1
  163. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_opd_resume_safety.py +24 -21
  164. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_opd_train.py +874 -22
  165. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_parasail_teacher.py +317 -29
  166. freesolo_flash_dev-1.2.89/tests/test_persisted_spec_envelope.py +93 -0
  167. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_provider_routing.py +47 -41
  168. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_provider_teardown_robustness.py +0 -12
  169. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_providers_symmetry.py +40 -2
  170. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_realized_cost.py +48 -44
  171. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_repo_cleanup.py +2 -2
  172. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_resume_on_retry.py +1 -1
  173. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_rl_train.py +1621 -104
  174. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_runmgmt.py +300 -58
  175. freesolo_flash_dev-1.2.89/tests/test_runpod_api_delete.py +155 -0
  176. freesolo_flash_dev-1.2.89/tests/test_runpod_key_fingerprint.py +400 -0
  177. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_serve.py +37 -5
  178. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_server_api.py +84 -154
  179. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_server_billing.py +10 -9
  180. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_server_envs_coverage.py +476 -32
  181. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_sft_train.py +387 -1
  182. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_spec_and_validation.py +278 -87
  183. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_spec_contract_bytes.py +2 -1
  184. freesolo_flash_dev-1.2.89/tests/test_staged_environment.py +916 -0
  185. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_step_metrics.py +70 -3
  186. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_step_timing.py +15 -0
  187. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_teacher_broker.py +514 -58
  188. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_training_controls.py +46 -9
  189. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_verifiers.py +96 -1
  190. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_verl_checkpoint_export.py +103 -0
  191. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_verl_child_plugins.py +31 -5
  192. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_vl_warmstart_adapter_keys.py +61 -42
  193. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_warmstart_adapter_download.py +43 -0
  194. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_warmstart_cross_repo.py +292 -83
  195. freesolo_flash_dev-1.2.89/tests/test_warmstart_image_adapters.py +222 -0
  196. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_weight_cache.py +3 -1
  197. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_worker_stack.py +7 -5
  198. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_workload_profile.py +1 -0
  199. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/uv.lock +7 -7
  200. freesolo_flash_dev-1.2.87/flash/core/spec_persistence.py +0 -414
  201. freesolo_flash_dev-1.2.87/tests/fixtures/math_eval.jsonl +0 -3
  202. freesolo_flash_dev-1.2.87/tests/fixtures/math_train.jsonl +0 -2
  203. freesolo_flash_dev-1.2.87/tests/test_env_ref_pinning.py +0 -313
  204. freesolo_flash_dev-1.2.87/tests/test_fused_expert_warmstart.py +0 -778
  205. freesolo_flash_dev-1.2.87/tests/test_opd_multiturn_failure_exit.py +0 -170
  206. freesolo_flash_dev-1.2.87/tests/test_persisted_spec_envelope.py +0 -255
  207. freesolo_flash_dev-1.2.87/tests/test_runpod_api_delete.py +0 -67
  208. freesolo_flash_dev-1.2.87/tests/test_runpod_key_fingerprint.py +0 -122
  209. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/.dockerignore +0 -0
  210. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/.env.example +0 -0
  211. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/.github/CODEOWNERS +0 -0
  212. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  213. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  214. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  215. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  216. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/.github/dependabot.yml +0 -0
  217. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/.github/workflows/auto-rebake.yml +0 -0
  218. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/.github/workflows/bake-kernel-cache.yml +0 -0
  219. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/.github/workflows/ci.yml +0 -0
  220. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/.github/workflows/dev-kernel-cache.yml +0 -0
  221. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/.github/workflows/main-source-guard.yml +0 -0
  222. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/.github/workflows/notify-tests-repo.yml +0 -0
  223. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/.github/workflows/production-kernel-cache-ready.yml +0 -0
  224. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/.github/workflows/publish-dev.yml +0 -0
  225. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/.github/workflows/publish-image.yml +0 -0
  226. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/.github/workflows/publish.yml +0 -0
  227. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/.github/workflows/version-parity.yml +0 -0
  228. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/.github/workflows/worker-image.yml +0 -0
  229. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/.gitignore +0 -0
  230. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/CHANGELOG.md +0 -0
  231. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/CODE_OF_CONDUCT.md +0 -0
  232. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/CONTRIBUTING.md +0 -0
  233. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/Dockerfile +0 -0
  234. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/Dockerfile.worker +0 -0
  235. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/LICENSE +0 -0
  236. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/NOTICE +0 -0
  237. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/README.md +0 -0
  238. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/SECURITY.md +0 -0
  239. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/SELF_HOSTING.md +0 -0
  240. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/build/kernel_cache/.gitignore +0 -0
  241. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/build/kernel_cache/.keep +0 -0
  242. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/deploy/infisical/README.md +0 -0
  243. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/deploy/infisical/entrypoint.sh +0 -0
  244. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/docker/Dockerfile.kernelcache +0 -0
  245. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/docker/Dockerfile.kernelcache.relayer +0 -0
  246. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/docker/bake_kernel_cache.py +0 -0
  247. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/docker/bake_pod_entry.py +0 -0
  248. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/docker/extract_cudart_fix.py +0 -0
  249. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/docker/kernel_fingerprint.py +0 -0
  250. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/docker/make_rp_handler.py +0 -0
  251. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/__init__.py +0 -0
  252. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/_internal/__init__.py +0 -0
  253. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/_internal/channel.py +0 -0
  254. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/_internal/diagnostics.py +0 -0
  255. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/_internal/fileio.py +0 -0
  256. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/_internal/logging.py +0 -0
  257. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/_internal/paths.py +0 -0
  258. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/adapters/__init__.py +0 -0
  259. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/__init__.py +0 -0
  260. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/__main__.py +0 -0
  261. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/commands/deploy.py +0 -0
  262. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/commands/env/__init__.py +0 -0
  263. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/commands/env/episode.py +0 -0
  264. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/commands/env/eval.py +0 -0
  265. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/commands/env/eval_args.py +0 -0
  266. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/commands/env/imports.py +0 -0
  267. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/commands/env/list.py +0 -0
  268. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/commands/env/retained.py +0 -0
  269. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/commands/env/setup.py +0 -0
  270. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/commands/env/setup_wandb.py +0 -0
  271. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/commands/env/test_evaluations.py +0 -0
  272. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/commands/env/test_params.py +0 -0
  273. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/commands/env/test_warnings.py +0 -0
  274. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/commands/prompt_budget.py +0 -0
  275. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/commands/traces.py +0 -0
  276. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/scaffold/__init__.py +0 -0
  277. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/ui/__init__.py +0 -0
  278. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/ui/cost.py +0 -0
  279. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/ui/env_panels.py +0 -0
  280. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/ui/heartbeat.py +0 -0
  281. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/ui/render.py +0 -0
  282. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/ui/tables.py +0 -0
  283. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/ui/tty.py +0 -0
  284. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/client/__init__.py +0 -0
  285. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/client/config.py +0 -0
  286. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/client/freesolo_api.py +0 -0
  287. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/client/http.py +0 -0
  288. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/client/runtime_secrets.py +0 -0
  289. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/client/shapes.py +0 -0
  290. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/client/specs.py +0 -0
  291. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/client/streaming.py +0 -0
  292. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/content/__init__.py +0 -0
  293. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/content/structured_outputs.py +0 -0
  294. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/content/thinking.py +0 -0
  295. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/core/__init__.py +0 -0
  296. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cost/__init__.py +0 -0
  297. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/__init__.py +0 -0
  298. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/huggingface.py +0 -0
  299. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/plan/__init__.py +0 -0
  300. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/plan/kv_sizing.py +0 -0
  301. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/plan/prompt_budget.py +0 -0
  302. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/plan/steps.py +0 -0
  303. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/plan/vram.py +0 -0
  304. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/profiling/__init__.py +0 -0
  305. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/profiling/dataset_profile.py +0 -0
  306. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/profiling/sft_image_rows.py +0 -0
  307. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/profiling/sft_workload.py +0 -0
  308. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/profiling/workload_profile.py +0 -0
  309. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/result/__init__.py +0 -0
  310. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/result/accounting.py +0 -0
  311. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/result/rollout_samples.py +0 -0
  312. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/__main__.py +0 -0
  313. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/backend_common.py +0 -0
  314. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/entry/__init__.py +0 -0
  315. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/entry/opd.py +0 -0
  316. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/entry/rl.py +0 -0
  317. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/io/__init__.py +0 -0
  318. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/io/hf.py +0 -0
  319. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/io/wandb_log.py +0 -0
  320. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/model/__init__.py +0 -0
  321. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/model/chatml_mask.py +0 -0
  322. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/model/decoding.py +0 -0
  323. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/model/packing.py +0 -0
  324. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/perf/__init__.py +0 -0
  325. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/perf/diagnostics.py +0 -0
  326. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/perf/lifecycle.py +0 -0
  327. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/perf/liger.py +0 -0
  328. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/perf/memory.py +0 -0
  329. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/runtime/__init__.py +0 -0
  330. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/runtime/kernel_warmup.py +0 -0
  331. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/runtime/pkg_proxy.py +0 -0
  332. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/runtime/rng.py +0 -0
  333. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/score_batcher.py +0 -0
  334. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/teacher/__init__.py +0 -0
  335. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/teacher/encoding.py +0 -0
  336. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/teacher/tokenizer_align.py +0 -0
  337. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/__init__.py +0 -0
  338. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/core/__init__.py +0 -0
  339. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/core/checkpoint_lifecycle.py +0 -0
  340. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/core/child/__init__.py +0 -0
  341. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/core/step_timing.py +0 -0
  342. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/finalize.py +0 -0
  343. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/opd/__init__.py +0 -0
  344. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/opd/bridge_failures.py +0 -0
  345. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/opd/child/__init__.py +0 -0
  346. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/opd/child/entry.py +0 -0
  347. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/opd/child/plugin.py +0 -0
  348. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/opd/child/structured.py +0 -0
  349. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/opd/multiturn_validation.py +0 -0
  350. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/opd/reporting.py +0 -0
  351. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/opd/validation.py +0 -0
  352. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/rl/__init__.py +0 -0
  353. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/rl/child/__init__.py +0 -0
  354. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/rl/child/entry.py +0 -0
  355. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/rl/config.py +0 -0
  356. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/rl/scoring.py +0 -0
  357. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/rl/single_turn.py +0 -0
  358. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/sft/__init__.py +0 -0
  359. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/sft/child/entry.py +0 -0
  360. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/verl/__init__.py +0 -0
  361. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/verl/capabilities.py +0 -0
  362. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/verl/diagnostics.py +0 -0
  363. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/verl/parallelism.py +0 -0
  364. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/verl/parent_work.py +0 -0
  365. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker_entrypoint.py +0 -0
  366. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/envs/__init__.py +0 -0
  367. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/envs/cache_security.py +0 -0
  368. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/envs/dataset_selection.py +0 -0
  369. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/envs/evaluations.py +0 -0
  370. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/envs/namespace_listing.py +0 -0
  371. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/envs/package/__init__.py +0 -0
  372. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/envs/package/direct_tokens.py +0 -0
  373. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/envs/package/limits.py +0 -0
  374. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/envs/package/unpack.py +0 -0
  375. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/envs/pull.py +0 -0
  376. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/__init__.py +0 -0
  377. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/_lifecycle/__init__.py +0 -0
  378. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/_lifecycle/auth.py +0 -0
  379. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/_lifecycle/bootstrap_console.py +0 -0
  380. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/_lifecycle/bootstrap_secrets.py +0 -0
  381. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/_lifecycle/deadline.py +0 -0
  382. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/_lifecycle/host/__init__.py +0 -0
  383. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/_lifecycle/host/deadline_sleep.py +0 -0
  384. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/_lifecycle/host/failmark.py +0 -0
  385. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/_lifecycle/host/hostlog.py +0 -0
  386. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/_lifecycle/http.py +0 -0
  387. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/_lifecycle/instance.py +0 -0
  388. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/_lifecycle/poll_instance.py +0 -0
  389. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/_lifecycle/provider.py +0 -0
  390. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/_lifecycle/terminal_artifacts.py +0 -0
  391. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/allocator.py +0 -0
  392. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/artifacts/__init__.py +0 -0
  393. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/artifacts/hf.py +0 -0
  394. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/artifacts/preload_runpod.py +0 -0
  395. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/base.py +0 -0
  396. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/fit_errors.py +0 -0
  397. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/lambda_/__init__.py +0 -0
  398. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/lambda_/api.py +0 -0
  399. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/lambda_/auth.py +0 -0
  400. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/lambda_/gpus.py +0 -0
  401. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/lambda_/jobs/__init__.py +0 -0
  402. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/lambda_/jobs/builders.py +0 -0
  403. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/lambda_/jobs/reap.py +0 -0
  404. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/lambda_/preflight.py +0 -0
  405. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/lambda_/pricing.py +0 -0
  406. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/preflight.py +0 -0
  407. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/runpod/auth.py +0 -0
  408. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/runpod/cost.py +0 -0
  409. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/runpod/gpus.py +0 -0
  410. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/runpod/job_execution.py +0 -0
  411. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/runpod/preflight.py +0 -0
  412. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/runpod/pricing.py +0 -0
  413. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/runpod/resources.py +0 -0
  414. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/runpod/serverless/__init__.py +0 -0
  415. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/sharding.py +0 -0
  416. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/vast/__init__.py +0 -0
  417. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/vast/api.py +0 -0
  418. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/vast/auth.py +0 -0
  419. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/vast/jobs/__init__.py +0 -0
  420. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/vast/jobs/builders.py +0 -0
  421. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/vast/preflight.py +0 -0
  422. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/vast/pricing.py +0 -0
  423. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/py.typed +0 -0
  424. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runner/attempts.py +0 -0
  425. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runner/deadlines.py +0 -0
  426. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runner/results/__init__.py +0 -0
  427. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runner/results/checkpoints.py +0 -0
  428. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runner/results/verified_revisions.py +0 -0
  429. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runner/supervise/__init__.py +0 -0
  430. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runner/supervise/retry_decision.py +0 -0
  431. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runner/weight_cache.py +0 -0
  432. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runtime_capsule/__init__.py +0 -0
  433. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runtime_capsule/build.py +0 -0
  434. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runtime_capsule/manifest.py +0 -0
  435. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runtime_capsule/profiles.py +0 -0
  436. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/serve/__init__.py +0 -0
  437. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/serve/adapter_check.py +0 -0
  438. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/serve/errors.py +0 -0
  439. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/serve/preflight.py +0 -0
  440. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/serve/responses.py +0 -0
  441. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/serve/streaming.py +0 -0
  442. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/serve/thinking.py +0 -0
  443. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/serve/urls.py +0 -0
  444. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/__init__.py +0 -0
  445. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/__main__.py +0 -0
  446. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/app.py +0 -0
  447. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/billing/__init__.py +0 -0
  448. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/billing/charges.py +0 -0
  449. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/billing/retry.py +0 -0
  450. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/domain/__init__.py +0 -0
  451. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/domain/checkpoints.py +0 -0
  452. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/domain/environment_registry.py +0 -0
  453. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/domain/envs.py +0 -0
  454. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/domain/projects.py +0 -0
  455. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/domain/run_registry.py +0 -0
  456. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/domain/teacher_requests.py +0 -0
  457. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/platform/__init__.py +0 -0
  458. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/platform/auth.py +0 -0
  459. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/platform/internal_client.py +0 -0
  460. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/platform/locks.py +0 -0
  461. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/platform/runtime.py +0 -0
  462. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/routes/__init__.py +0 -0
  463. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/routes/envs.py +0 -0
  464. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/routes/meta.py +0 -0
  465. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/routes/runs.py +0 -0
  466. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/routes/serving_completion.py +0 -0
  467. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/routes/teacher.py +0 -0
  468. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/source_snapshot.py +0 -0
  469. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/teacher/__init__.py +0 -0
  470. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/teacher/limits.py +0 -0
  471. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/scripts/build_dev_dist.py +0 -0
  472. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/scripts/check_file_size.py +0 -0
  473. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/scripts/check_function_size.py +0 -0
  474. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/scripts/check_verl_pin_exists.py +0 -0
  475. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/scripts/scrub_history.sh +0 -0
  476. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/__init__.py +0 -0
  477. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/_helpers/__init__.py +0 -0
  478. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/_helpers/profile.py +0 -0
  479. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/_helpers/source_snapshot.py +0 -0
  480. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/_helpers/specs.py +0 -0
  481. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/_helpers/teacher.py +0 -0
  482. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/_helpers/vast.py +0 -0
  483. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/capture_image_sft_processor_oracle.py +0 -0
  484. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/conftest.py +0 -0
  485. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/fixtures/image_sft_processor_oracle.json +0 -0
  486. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/live/__init__.py +0 -0
  487. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/live/conftest.py +0 -0
  488. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/live/test_lambda_live.py +0 -0
  489. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/live/test_runpod_live.py +0 -0
  490. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/live/test_sft_thinking_render_live.py +0 -0
  491. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/live/test_vast_live.py +0 -0
  492. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_accounting_coverage.py +0 -0
  493. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_algorithms.py +0 -0
  494. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_backend_jobspec_contract.py +0 -0
  495. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_bake_kernel_cache.py +0 -0
  496. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_base_model_provenance.py +0 -0
  497. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_build_context_contract.py +0 -0
  498. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_catalog_consistency.py +0 -0
  499. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_catalog_only_models.py +0 -0
  500. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_charge_pricing.py +0 -0
  501. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_checkpoint_lifecycle.py +0 -0
  502. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_cli_commands_coverage.py +0 -0
  503. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_cli_credential_shadowing.py +0 -0
  504. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_cli_errors.py +0 -0
  505. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_cli_gpus_flag.py +0 -0
  506. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_cli_help.py +0 -0
  507. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_cli_main_coverage.py +0 -0
  508. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_cli_managed.py +0 -0
  509. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_cli_render_theme.py +0 -0
  510. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_cli_traces.py +0 -0
  511. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_cli_wandb_warning.py +0 -0
  512. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_client.py +0 -0
  513. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_client_import_purity.py +0 -0
  514. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_client_server_integration.py +0 -0
  515. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_client_stream_reads.py +0 -0
  516. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_config_env_vars.py +0 -0
  517. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_config_overrides.py +0 -0
  518. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_console_upload.py +0 -0
  519. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_cost_models.py +0 -0
  520. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_deploy_alias_move_warning.py +0 -0
  521. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_deploy_latency.py +0 -0
  522. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_dev_channel.py +0 -0
  523. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_endpoint_name.py +0 -0
  524. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_env_cache_evict.py +0 -0
  525. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_env_delete.py +0 -0
  526. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_env_download.py +0 -0
  527. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_env_download_api.py +0 -0
  528. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_env_list_api.py +0 -0
  529. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_env_list_cli.py +0 -0
  530. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_env_list_hub.py +0 -0
  531. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_env_no_install.py +0 -0
  532. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_env_publish.py +0 -0
  533. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_env_pull.py +0 -0
  534. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_env_pull_coverage.py +0 -0
  535. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_env_pull_loader_coverage.py +0 -0
  536. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_env_pull_managed_control_plane.py +0 -0
  537. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_envs_coverage.py +0 -0
  538. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_flash_mvp.py +0 -0
  539. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_flashinfer_cache_dirs.py +0 -0
  540. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_freesolo_api_transport.py +0 -0
  541. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_github_urlopen_retry.py +0 -0
  542. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_gpu_type_single_field.py +0 -0
  543. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_gpus.py +0 -0
  544. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_grpo_resident_sizing.py +0 -0
  545. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_health_liveness.py +0 -0
  546. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_hf_retry.py +0 -0
  547. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_idle_endpoint_reaper.py +0 -0
  548. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_image_sft_markers.py +0 -0
  549. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_image_sft_processor_parity.py +0 -0
  550. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_infisical_secrets.py +0 -0
  551. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_internal_client.py +0 -0
  552. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_kernel_cache.py +0 -0
  553. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_kernel_fingerprint.py +0 -0
  554. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_kv_util.py +0 -0
  555. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_lambda_api_coverage.py +0 -0
  556. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_logging.py +0 -0
  557. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_login_perms.py +0 -0
  558. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_managed_config_fields.py +0 -0
  559. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_managed_hf_repo.py +0 -0
  560. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_metrics_schema_agent_contract.py +0 -0
  561. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_mig_guard.py +0 -0
  562. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_named_reward_metrics.py +0 -0
  563. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_opd_limits.py +0 -0
  564. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_opd_multiturn_eos_boundary.py +0 -0
  565. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_orchestrator_flash.py +0 -0
  566. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_packing.py +0 -0
  567. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_packing_coverage.py +0 -0
  568. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_poll_helpers.py +0 -0
  569. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_preflight.py +0 -0
  570. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_projects.py +0 -0
  571. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_prompt_budget.py +0 -0
  572. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_provider_preflight_coverage.py +0 -0
  573. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_resolve_params_b.py +0 -0
  574. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_rollout_samples.py +0 -0
  575. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_runpod_key_waterfall.py +0 -0
  576. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_runtime_capsule.py +0 -0
  577. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_serve_reasoning_content.py +0 -0
  578. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_server_app_coverage.py +0 -0
  579. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_server_auth_singleflight.py +0 -0
  580. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_server_checkpoints_coverage.py +0 -0
  581. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_server_db.py +0 -0
  582. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_server_locks_coverage.py +0 -0
  583. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_server_standalone.py +0 -0
  584. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_serving_context_preflight.py +0 -0
  585. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_serving_contract.py +0 -0
  586. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_serving_schema_coverage.py +0 -0
  587. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_sft_chunked_nll.py +0 -0
  588. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_sft_example_selection.py +0 -0
  589. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_sft_gc_off.py +0 -0
  590. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_sft_max_context.py +0 -0
  591. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_sft_startup_block.py +0 -0
  592. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_sft_workload.py +0 -0
  593. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_source_attestation_flow.py +0 -0
  594. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_source_snapshot.py +0 -0
  595. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_step_floor.py +0 -0
  596. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_structured_outputs.py +0 -0
  597. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_teacher_encoding_contract.py +0 -0
  598. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_terminal_artifacts.py +0 -0
  599. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_thinking_config.py +0 -0
  600. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_train_context_preflight.py +0 -0
  601. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_type_comment_prose.py +0 -0
  602. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_vast_api.py +0 -0
  603. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_vast_api_coverage.py +0 -0
  604. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_vast_offers.py +0 -0
  605. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_vast_provider_coverage.py +0 -0
  606. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_vast_runner.py +0 -0
  607. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_verified_revisions.py +0 -0
  608. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_verl_silence_watchdog.py +0 -0
  609. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_version.py +0 -0
  610. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_vram_architecture.py +0 -0
  611. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_wandb_link.py +0 -0
  612. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_wandb_naming.py +0 -0
  613. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_warmstart_error_attribution.py +0 -0
  614. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_worker_dryrun.py +0 -0
  615. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_worker_hardexit.py +0 -0
  616. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_worker_image.py +0 -0
  617. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_worker_init_heartbeat.py +0 -0
  618. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_worker_thinking.py +0 -0
  619. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_workflow_contracts.py +0 -0
  620. {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/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.87
3
+ Version: 1.2.89
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
@@ -5,15 +5,13 @@ by it, and the two never share a call stack to check. Spelling one on each side
5
5
  coincidence, so they are defined once, here.
6
6
  """
7
7
 
8
- # The PEFT adapter weights file a deployable adapter must carry. Modern saves use safetensors,
9
- # but older PEFT/default settings may emit adapter_model.bin.
10
- ADAPTER_WEIGHT_FILES = ("adapter_model.safetensors", "adapter_model.bin")
8
+ # the peft adapter weights file a deployable adapter must carry.
9
+ ADAPTER_WEIGHT_FILES = ("adapter_model.safetensors",)
11
10
 
12
- # A PEFT save past its shard size splits the weights across `adapter_model-0000N-of-0000M.<ext>`
11
+ # a peft save past its shard size splits the weights across `adapter_model-0000N-of-0000M.<ext>`
13
12
  # beside an `adapter_model.<ext>.index.json` mapping every tensor key to the shard holding it.
14
13
  ADAPTER_SHARD_PREFIX = "adapter_model-"
15
- ADAPTER_WEIGHT_SUFFIXES = (".safetensors", ".bin")
16
- ADAPTER_WEIGHT_INDEX_FILES = tuple(f"{name}.index.json" for name in ADAPTER_WEIGHT_FILES)
14
+ ADAPTER_WEIGHT_SUFFIXES = (".safetensors",)
17
15
 
18
16
 
19
17
  def is_adapter_weight_filename(filename: str) -> bool:
@@ -9,8 +9,8 @@ from typing import Any
9
9
 
10
10
  from flash.adapters.lora_rank import (
11
11
  _rank_for_module,
12
- declared_lora_ranks,
13
12
  lora_tensor_rank_disagrees,
13
+ strict_declared_lora_ranks,
14
14
  )
15
15
  from flash.core.catalog import get_model
16
16
 
@@ -31,10 +31,23 @@ _QWEN36_FUSED_TARGET_RUNGS = {
31
31
  }
32
32
  _FUSED_EXPERT_SYNTHETIC_MODULES = frozenset({"experts", "base_layer"})
33
33
  _FUSED_EXPERT_WRAPPER_MODULES = ("mlp.experts", "mlp.experts.base_layer")
34
+ _NON_LANGUAGE_LORA_SEGMENTS = frozenset(
35
+ {
36
+ "mtp",
37
+ "multi_modal_projector",
38
+ "patch_embed",
39
+ "visual",
40
+ "vision",
41
+ "vision_encoder",
42
+ "vision_model",
43
+ "vision_tower",
44
+ }
45
+ )
34
46
  _INVALID_FUSED_LOCATION = object()
35
47
 
36
48
  _LoraTensor = tuple[str, str, str, tuple[int, ...]]
37
49
  _LoraPair = tuple[tuple[int, ...], tuple[int, ...]]
50
+ _LoraPairKeys = tuple[str, str]
38
51
 
39
52
 
40
53
  def lora_target_parameters(model_id: str | None) -> list[str] | None:
@@ -67,9 +80,7 @@ def validate_fused_expert_adapter_config(config: Mapping[str, Any], model_id: st
67
80
  f"adapter for {model_id} must declare exactly the fused expert targets {required}"
68
81
  )
69
82
 
70
- rank_pattern = config.get("rank_pattern")
71
- _validate_rank_pattern(rank_pattern, model_id)
72
- declared = declared_lora_ranks(config)
83
+ declared = strict_declared_lora_ranks(config, source=f"adapter for {model_id}")
73
84
  unresolved = [target for target in required if _rank_for_module(target, declared) is None]
74
85
  if unresolved:
75
86
  raise ValueError(
@@ -109,31 +120,6 @@ def validate_fused_expert_adapter_config(config: Mapping[str, Any], model_id: st
109
120
  )
110
121
 
111
122
 
112
- def _validate_rank_pattern(rank_pattern: Any, model_id: str) -> None:
113
- """Validate positive ranks and PEFT's anchored regex pattern syntax."""
114
- message = (
115
- f"adapter for {model_id} rank_pattern must map valid non-empty string patterns "
116
- "to positive integer ranks"
117
- )
118
- if rank_pattern is None:
119
- return
120
- if not isinstance(rank_pattern, Mapping):
121
- raise ValueError(message)
122
- for pattern, rank in rank_pattern.items():
123
- if (
124
- not isinstance(pattern, str)
125
- or not pattern.strip()
126
- or not isinstance(rank, int)
127
- or isinstance(rank, bool)
128
- or rank <= 0
129
- ):
130
- raise ValueError(message)
131
- try:
132
- re.compile(rf"(.*\.)?({pattern})$")
133
- except re.error as exc:
134
- raise ValueError(message) from exc
135
-
136
-
137
123
  def _targets_fused_expert_wrapper(module: str) -> bool:
138
124
  """Return whether PEFT suffix matching binds this target to an expert wrapper."""
139
125
  return any(
@@ -161,6 +147,33 @@ def normalize_verl_fused_expert_export(config: dict[str, Any], model_id: str) ->
161
147
  ]
162
148
 
163
149
 
150
+ def is_non_language_lora_key(key: str) -> bool:
151
+ """whether a LoRA tensor key names a non-language (vision, projector, mtp) module."""
152
+ return bool(set(key.lower().split(".")) & _NON_LANGUAGE_LORA_SEGMENTS)
153
+
154
+
155
+ def fused_expert_lora_tensor_pairs(
156
+ tensors: Mapping[str, tuple[int, ...]], config: Mapping[str, Any], model_id: str
157
+ ) -> dict[str, _LoraPairKeys] | None:
158
+ """Return complete canonical pair keys when fused and ordinary topology is exact."""
159
+ expected = _expected_fused_expert_rungs(config, model_id)
160
+ if expected is None:
161
+ return None
162
+ lora_keys = {key: shape for key, shape in tensors.items() if _LORA_FACTOR_PATTERN.search(key)}
163
+ parsed = [
164
+ tensor
165
+ for key, shape in lora_keys.items()
166
+ if (tensor := _parse_lora_tensor(key, shape)) is not None
167
+ ]
168
+ if not parsed or len(parsed) != len(lora_keys):
169
+ return None
170
+ if not _has_complete_fused_rungs(parsed, expected, model_id) or not _has_ordinary_evidence(
171
+ parsed, config, expected
172
+ ):
173
+ return None
174
+ return _complete_lora_pair_keys(parsed)
175
+
176
+
164
177
  def has_complete_fused_expert_tensors(
165
178
  tensors: Mapping[str, tuple[int, ...]], config: Mapping[str, Any], model_id: str
166
179
  ) -> bool:
@@ -225,7 +238,7 @@ def _expected_fused_expert_rungs(
225
238
  if catalog_dimensions != Counter(_QWEN36_FUSED_TARGET_DIMENSIONS.values()):
226
239
  return None
227
240
 
228
- declared = declared_lora_ranks(config)
241
+ declared = strict_declared_lora_ranks(config)
229
242
  expected: dict[str, dict[str, _LoraPair]] = {}
230
243
  for target in targets:
231
244
  rank = _rank_for_module(target, declared)
@@ -315,15 +328,17 @@ def _has_ordinary_evidence(
315
328
  for module_path, factor, key, shape in tensors:
316
329
  if _is_fused_rung(module_path, fused_rungs):
317
330
  continue
331
+ if not module_path.startswith("base_model.model."):
332
+ return False
318
333
  matched = tuple(target for target in targets if _anchored_suffix_match(module_path, target))
319
334
  if not all_linear and not matched:
320
- continue
335
+ return False
321
336
  evidence.update(matched)
322
337
  groups.setdefault(module_path, {})[factor] = (key, shape)
323
338
  if not groups or (not all_linear and evidence != set(targets)):
324
339
  return False
325
340
 
326
- declared = declared_lora_ranks(config)
341
+ declared = strict_declared_lora_ranks(config)
327
342
  for module_path, factors in groups.items():
328
343
  if _rank_for_module(module_path, declared) is None:
329
344
  return False
@@ -335,6 +350,21 @@ def _has_ordinary_evidence(
335
350
  return True
336
351
 
337
352
 
353
+ def _complete_lora_pair_keys(
354
+ tensors: list[_LoraTensor],
355
+ ) -> dict[str, _LoraPairKeys] | None:
356
+ """Return every canonical module pair without orphan factors."""
357
+ groups: dict[str, dict[str, str]] = {}
358
+ for module_path, factor, key, _shape in tensors:
359
+ factors = groups.setdefault(module_path, {})
360
+ if factor in factors:
361
+ return None
362
+ factors[factor] = key
363
+ if not groups or any(set(factors) != {"A", "B"} for factors in groups.values()):
364
+ return None
365
+ return {module_path: (factors["A"], factors["B"]) for module_path, factors in groups.items()}
366
+
367
+
338
368
  def _is_fused_rung(module_path: str, fused_rungs: Mapping[str, Mapping[str, _LoraPair]]) -> bool:
339
369
  """Return whether a module path is one of the exact fused wrapper rungs."""
340
370
  return any(
@@ -105,13 +105,16 @@ def _positive_int(value: Any, *, source: str, field: str) -> int:
105
105
 
106
106
 
107
107
  def _file_identity(file_info: Any) -> str:
108
+ # the producer is `HfApi.list_repo_tree`, which yields `RepoFile` -- whose `__init__` always
109
+ # sets `path`/`size`/`blob_id` and builds `lfs` as a `BlobLfsInfo` (field `sha256`, no `oid`).
110
+ # verified at the declared floor `huggingface-hub>=1.2.0` and at the installed 1.27.0, so the
111
+ # mapping-shaped `lfs` and the `lfs.oid` spelling have no producer in the supported range.
112
+ # `getattr` stays only on `lfs` itself, which is legitimately optional (non-LFS files), and on
113
+ # the entry object, because a listing also yields `RepoFolder` -- no size, no blob_id -- which
114
+ # must fail closed rather than hash to a folder's tree id.
108
115
  lfs = getattr(file_info, "lfs", None)
109
- if isinstance(lfs, Mapping):
110
- oid = lfs.get("sha256") or lfs.get("oid")
111
- size = lfs.get("size")
112
- else:
113
- oid = getattr(lfs, "sha256", None) or getattr(lfs, "oid", None)
114
- size = getattr(lfs, "size", None)
116
+ oid = getattr(lfs, "sha256", None)
117
+ size = getattr(lfs, "size", None)
115
118
  blob_id = getattr(file_info, "blob_id", None)
116
119
  size = size if size is not None else getattr(file_info, "size", None)
117
120
  immutable = oid or blob_id
@@ -281,6 +284,8 @@ def rank_from_adapter_config(config: Mapping[str, Any], *, source: str) -> int:
281
284
 
282
285
  _LORA_A_INFIX = ".lora_A."
283
286
  _LORA_B_INFIX = ".lora_B."
287
+ # PEFT appends this rung for every parameter wrapper nested inside another one.
288
+ _NESTED_WRAPPER_RUNG = ".base_layer"
284
289
 
285
290
 
286
291
  @dataclass(frozen=True)
@@ -296,26 +301,9 @@ class DeclaredLoraRanks:
296
301
  return self.default is not None or bool(self.by_module)
297
302
 
298
303
 
299
- def declared_lora_ranks(config: Mapping[str, Any]) -> DeclaredLoraRanks:
300
- """Read the per-module LoRA rank structure out of ``adapter_config.json``."""
301
- if not isinstance(config, Mapping):
302
- return DeclaredLoraRanks()
303
- try:
304
- default = _positive_int(config["r"], source="adapter_config.json", field="r")
305
- except (KeyError, ValueError):
306
- default = None
307
-
308
- by_module: dict[str, int] = {}
309
- pattern = config.get("rank_pattern")
310
- if isinstance(pattern, Mapping):
311
- for module, value in pattern.items():
312
- try:
313
- by_module[str(module)] = _positive_int(
314
- value, source="adapter_config.json", field="rank_pattern"
315
- )
316
- except ValueError:
317
- continue
318
-
304
+ def _declared_lora_rank_context(
305
+ config: Mapping[str, Any], *, default: int | None, by_module: Mapping[str, int]
306
+ ) -> DeclaredLoraRanks:
319
307
  stacked_rank_modules: list[str] = []
320
308
  targets = config.get("target_parameters")
321
309
  if isinstance(targets, list):
@@ -335,6 +323,41 @@ def declared_lora_ranks(config: Mapping[str, Any]) -> DeclaredLoraRanks:
335
323
  )
336
324
 
337
325
 
326
+ def strict_declared_lora_ranks(
327
+ config: Mapping[str, Any], *, source: str = "adapter_config.json"
328
+ ) -> DeclaredLoraRanks:
329
+ """validate and preserve PEFT rank declarations for an authoritative load boundary."""
330
+ if not isinstance(config, Mapping):
331
+ raise ValueError(f"{source} must be an object")
332
+
333
+ default = None
334
+ if "r" in config:
335
+ value = config["r"]
336
+ if not isinstance(value, int) or isinstance(value, bool) or value <= 0:
337
+ raise ValueError(f"{source} r must be a positive integer")
338
+ default = value
339
+
340
+ by_module: dict[str, int] = {}
341
+ if "rank_pattern" in config:
342
+ pattern = config["rank_pattern"]
343
+ if not isinstance(pattern, Mapping):
344
+ raise ValueError(f"{source} rank_pattern must be an object")
345
+ for module, value in pattern.items():
346
+ if not isinstance(module, str) or not module.strip():
347
+ raise ValueError(f"{source} rank_pattern keys must be non-empty strings")
348
+ if not isinstance(value, int) or isinstance(value, bool) or value <= 0:
349
+ raise ValueError(f"{source} rank_pattern values must be positive integers")
350
+ try:
351
+ re.compile(rf"(.*\.)?({module})$")
352
+ except re.error as exc:
353
+ raise ValueError(
354
+ f"{source} rank_pattern contains invalid regex {module!r}"
355
+ ) from exc
356
+ by_module[module] = value
357
+
358
+ return _declared_lora_rank_context(config, default=default, by_module=by_module)
359
+
360
+
338
361
  def _rank_for_module(module_path: str, declared: DeclaredLoraRanks) -> int | None:
339
362
  """Resolve a module's rank with PEFT's ordered, anchored ``rank_pattern`` matching."""
340
363
  for module, rank in declared.by_module.items():
@@ -350,9 +373,27 @@ def _rank_for_module(module_path: str, declared: DeclaredLoraRanks) -> int | Non
350
373
 
351
374
 
352
375
  def _module_uses_target_parameters(module_path: str, declared: DeclaredLoraRanks) -> bool:
353
- """Whether this serialized module came from one of PEFT's targeted parameters."""
376
+ """Whether this serialized module came from one of PEFT's targeted parameters.
377
+
378
+ PEFT wraps the module that *owns* a targeted parameter, keeping the parameter name off the
379
+ serialized path. When several targeted parameters share one owner, the wrappers nest and every
380
+ wrapper after the first appends a ``base_layer`` rung, so a single owner produces keys like::
381
+
382
+ mlp.experts (the outermost wrapper)
383
+ mlp.experts.base_layer (the one nested inside it)
384
+
385
+ Those inner rungs carry the same stacked axis as the outer one, so peeling the ``base_layer``
386
+ rungs off before matching is what keeps a valid adapter from being measured against the scalar
387
+ rank.
388
+ """
389
+ candidates = [module_path]
390
+ trimmed = module_path
391
+ while trimmed.endswith(_NESTED_WRAPPER_RUNG):
392
+ trimmed = trimmed[: -len(_NESTED_WRAPPER_RUNG)]
393
+ candidates.append(trimmed)
354
394
  return any(
355
- module_path == module or module_path.endswith(f".{module}")
395
+ candidate == module or candidate.endswith(f".{module}")
396
+ for candidate in candidates
356
397
  for module in declared.stacked_rank_modules
357
398
  )
358
399
 
@@ -409,11 +450,22 @@ def inspect_adapter_config(
409
450
  raise ValueError(f"could not verify adapter metadata: {source} is not a JSON object")
410
451
  if str(config.get("peft_type") or "").strip().upper() != "LORA":
411
452
  raise ValueError(f"could not verify adapter metadata: {source} peft_type must be LORA")
453
+ # both fields are REQUIRED, not "checked when present": every warm-start source is a
454
+ # flash-owned adapter resolved from a run or checkpoint reference, and the one exporter every
455
+ # publish path funnels through stamps `base_model_name_or_path = model_id` unconditionally
456
+ # (engine/worker/verl/checkpoints.py) while the builder always sets `task_type = CAUSAL_LM`
457
+ # (engine/worker/model/adapter.py). treating a blank value as "no opinion" made the base-model
458
+ # match SKIP itself, so an adapter trained on a different base passed preflight and was
459
+ # inherited into the run -- the check failing open is worse than an old artifact failing loudly.
412
460
  task_type = str(config.get("task_type") or "").strip().upper()
413
- if task_type and task_type != "CAUSAL_LM":
461
+ if task_type != "CAUSAL_LM":
414
462
  raise ValueError(f"could not verify adapter metadata: {source} task_type must be CAUSAL_LM")
415
463
  base_model = _normalized_model(config.get("base_model_name_or_path"))
416
- if base_model and base_model != _normalized_model(target_model):
464
+ if not base_model:
465
+ raise ValueError(
466
+ f"could not verify adapter metadata: {source} does not name its base model"
467
+ )
468
+ if base_model != _normalized_model(target_model):
417
469
  raise ValueError(
418
470
  f"train.init_from_adapter base model {base_model!r} does not match target model "
419
471
  f"{target_model!r}"
@@ -0,0 +1,61 @@
1
+ """Resolve the exact LoRA module surface for one training job."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import re
6
+ from collections.abc import Mapping
7
+ from dataclasses import dataclass
8
+ from typing import Any
9
+
10
+ from flash.adapters.fused_experts import lora_target_parameters
11
+ from flash.core.catalog import validate_model_for_algorithm
12
+
13
+
14
+ @dataclass(frozen=True)
15
+ class LoraTargeting:
16
+ target_modules: str
17
+ target_parameters: list[str] | None
18
+ exclude_modules: str | None
19
+
20
+
21
+ def require_modality_marker(config: Mapping[str, Any], *, source: str) -> None:
22
+ """Reject an adapter config that carries no ``exclude_modules`` modality marker.
23
+
24
+ Homed here, beside the resolver that WRITES the marker, so the control plane and the worker
25
+ decide this identically -- and called from both. The control plane already downloads this exact
26
+ config during warm-start preparation, so rejecting there costs a submit-time error, while the
27
+ worker-only check that used to be the sole gate could not fire until a GPU had been allocated
28
+ and the adapter re-downloaded. Same rejection, no paid allocation.
29
+
30
+ The worker keeps its own call because it validates the config it actually loads: the two
31
+ processes never share a call stack, so a marker present at preparation is not proof of one in
32
+ the bytes the trainer opens.
33
+
34
+ Every supported install writes the key -- ``peft>=0.19`` serializes ``exclude_modules`` on every
35
+ ``LoraConfig``, as null for a multimodal run -- so an absent key means the artifact predates the
36
+ marker entirely and its modality is unknowable. Guessing it is what this rejects: a text-only
37
+ adapter continued as multimodal (or the reverse) trains the wrong module surface and silently
38
+ produces an adapter that serves as a no-op.
39
+ """
40
+ if "exclude_modules" not in config:
41
+ raise ValueError(
42
+ f"{source} is missing the required exclude_modules modality marker; "
43
+ "unmarked artifacts are unsupported"
44
+ )
45
+
46
+
47
+ def resolve_lora_targeting(model_id: str, *, algorithm: str, multimodal: bool) -> LoraTargeting:
48
+ """Resolve fresh-training targets without changing an authored warm-start adapter."""
49
+ model = validate_model_for_algorithm(model_id, algorithm)
50
+ exclude_modules = None
51
+ if not multimodal:
52
+ prefix = model.lora_language_prefix.strip(".")
53
+ if not prefix:
54
+ raise ValueError(f"{model_id} has no cataloged text-only LoRA language module prefix")
55
+ escaped = re.escape(prefix)
56
+ exclude_modules = rf"^(?!{escaped}(?:\.|$)).*$"
57
+ return LoraTargeting(
58
+ target_modules="all-linear",
59
+ target_parameters=lora_target_parameters(model_id),
60
+ exclude_modules=exclude_modules,
61
+ )
@@ -15,12 +15,12 @@ from flash.cli.ui import render
15
15
  from flash.cli.ui.tty import TtyStatusLine
16
16
  from flash.client import (
17
17
  ApiClient,
18
- ApiError,
19
18
  ClientError,
20
19
  client_from_config,
21
20
  save_credentials,
22
21
  verify_freesolo_key,
23
22
  )
23
+ from flash.client import ApiError as ApiError
24
24
 
25
25
  # `shadowed_login_warning` has no call site left here since the cost quote moved to
26
26
  # `.train_cost`, but the estimate tests patch it on THIS module and that quote reads it back
@@ -380,18 +380,12 @@ def cmd_train(args) -> int:
380
380
  # dry-run runs submit-time server preflights without allocating a training gpu or charging
381
381
  # for training. a rejection surfaces as the server's error with exit status 1. for sft the
382
382
  # server reads the packaged dataset file and builds the quote without executing environment.py.
383
- try:
384
- status = client.create_run(
385
- payload,
386
- runtime_secrets=runtime_secrets,
387
- dry_run=True,
388
- client_train_schema=client_train_schema,
389
- )
390
- except ApiError as exc:
391
- detail = _legacy_train_key_rejection_detail(exc, authored_train_keys)
392
- if detail is None:
393
- raise
394
- raise ApiError(exc.status, detail, detail=detail) from exc
383
+ status = client.create_run(
384
+ payload,
385
+ runtime_secrets=runtime_secrets,
386
+ dry_run=True,
387
+ client_train_schema=client_train_schema,
388
+ )
395
389
  compatibility = status.pop("train_schema_compatibility", None)
396
390
  _print_train_schema_compatibility(compatibility)
397
391
  # the server fails open on a billing-infra problem, so "cost" is only in the validated list
@@ -979,7 +973,6 @@ from flash.cli.commands.train_cost import ( # noqa: E402,F401
979
973
  _cmd_train_cost,
980
974
  _cmd_train_cost_offline,
981
975
  _cmd_train_cost_sft,
982
- _legacy_train_key_rejection_detail,
983
976
  _print_reasoning_loss_warning,
984
977
  _print_sft_cost,
985
978
  _print_train_schema_compatibility,
@@ -18,6 +18,7 @@ from typing import TYPE_CHECKING, Literal, TypeAlias
18
18
  from flash._internal.channel import CLI_NAME
19
19
  from flash.cli.ui import render
20
20
  from flash.cli.ui.tty import TtyStatusLine
21
+ from flash.envs.package.limits import ARCHIVE_MEMBER_LIMIT as _ENV_PUSH_MAX_FILES
21
22
 
22
23
  if TYPE_CHECKING:
23
24
  from flash.client.http import ProgressCallback
@@ -336,11 +337,6 @@ _ENV_PUSH_SECRET_PATTERNS = (
336
337
  _ENV_PUSH_CODE_SUFFIXES = frozenset({".py", ".pyi"})
337
338
  _ENV_PUSH_MAX_TOTAL_BYTES = 256 * 1024 * 1024
338
339
 
339
- try:
340
- from flash.envs.package.limits import ARCHIVE_MEMBER_LIMIT as _ENV_PUSH_MAX_FILES
341
- except ImportError:
342
- _ENV_PUSH_MAX_FILES = 5000
343
-
344
340
 
345
341
  def _normalize_env_name(raw: str) -> str | None:
346
342
  """Normalize only the NAME segment; a ``<namespace>/<project>`` prefix passes through verbatim.
@@ -634,30 +630,18 @@ def _resolve_local_env_entrypoint(path: str | Path) -> tuple[Path, Path, Path, b
634
630
  include_full_tree = src.is_dir()
635
631
  if include_full_tree:
636
632
  canonical_entrypoint = src / _ENV_ENTRYPOINT
637
- if canonical_entrypoint.is_file():
638
- entrypoint = canonical_entrypoint
639
- env_root = src
640
- elif (src / "pyproject.toml").is_file():
641
- raise ValueError(f"{src} has a pyproject.toml but no environment.py entrypoint")
642
- else:
643
- # evaluations.py is a known sidecar, never an entrypoint. counting it here would
644
- # make adding one break a legacy single-module package that resolved fine before:
645
- # the directory would suddenly hold "multiple top-level .py modules" and be rejected
646
- # before either file is read.
647
- modules = [
648
- p
649
- for p in sorted(src.glob("*.py"))
650
- if not p.name.startswith("__") and p.name != _ENV_EVALUATIONS_SIDECAR
651
- ]
652
- if len(modules) != 1:
653
- raise ValueError(
654
- f"{src} has no environment.py and "
655
- f"{'no' if not modules else 'multiple'} top-level .py module(s); "
656
- "add an environment.py entrypoint or pass the exact .py file "
657
- "for a single-file smoke test."
658
- )
659
- env_root = src
660
- entrypoint = modules[0]
633
+ if not canonical_entrypoint.is_file():
634
+ # a directory package names its entrypoint `environment.py`. that is what `flash env
635
+ # setup` scaffolds and the only layout the docs describe, so a directory without one is
636
+ # rejected rather than guessed at: inferring the entrypoint from "the sole top-level
637
+ # module" made the resolution depend on which OTHER files happened to be present, so
638
+ # adding a second module turned a working push into a rejection.
639
+ raise ValueError(
640
+ f"{src} has no {_ENV_ENTRYPOINT} entrypoint; add one, "
641
+ "or pass the exact .py file for a single-file smoke test."
642
+ )
643
+ entrypoint = canonical_entrypoint
644
+ env_root = src
661
645
  elif src.is_file() and src.suffix == ".py":
662
646
  env_root = src.parent
663
647
  entrypoint = src
@@ -270,7 +270,11 @@ def _drive_single_turn(env, example: dict, record: dict, *, force_echo: bool = F
270
270
 
271
271
  def _new_multi_turn_replay_state(env, example: dict, record: dict) -> dict:
272
272
  state = env.new_rollout_state(example)
273
- record["prompt"] = _check_messages(state.get("prompt") or state.get("messages"), "prompt")
273
+ # `prompt` only, never `messages`: the two are not spellings of one field. `new_rollout_state`
274
+ # seeds `messages` with a COPY of `prompt` and appends each turn onto it, so falling back to it
275
+ # records the growing transcript where the frozen initial prefix belongs. every producer sets
276
+ # both, so an absent `prompt` is a corrupt state and `_check_messages` rejects it by name.
277
+ record["prompt"] = _check_messages(state.get("prompt"), "prompt")
274
278
  _normalize_prompt_images(env, example, record["prompt"])
275
279
  return state
276
280