freesolo-flash-dev 0.2.41__tar.gz → 0.2.43__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 (300) hide show
  1. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/Dockerfile.worker +6 -1
  2. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/PKG-INFO +1 -1
  3. freesolo_flash_dev-0.2.43/docs/cli-style/env-setup-survey-dark.png +0 -0
  4. freesolo_flash_dev-0.2.43/docs/cli-style/env-setup-survey-light.png +0 -0
  5. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/cli/__init__.py +25 -1
  6. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/cli/commands.py +106 -15
  7. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/cli/render.py +32 -0
  8. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/engine/worker/__init__.py +10 -0
  9. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/engine/worker/kernel_warmup.py +18 -1
  10. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/engine/worker/perf/__init__.py +135 -1
  11. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/engine/worker/sft.py +16 -6
  12. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/_worker.py +8 -5
  13. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/pyproject.toml +2 -2
  14. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_cli_commands.py +103 -0
  15. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_flash_worker.py +1 -1
  16. freesolo_flash_dev-0.2.43/tests/test_sft_example_selection.py +36 -0
  17. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_worker_stack.py +225 -6
  18. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/uv.lock +1 -1
  19. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/.dockerignore +0 -0
  20. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/.env.example +0 -0
  21. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/.github/workflows/auto-rebake.yml +0 -0
  22. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/.github/workflows/bake-kernel-cache.yml +0 -0
  23. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/.github/workflows/ci.yml +0 -0
  24. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/.github/workflows/main-source-guard.yml +0 -0
  25. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/.github/workflows/notify-tests-repo.yml +0 -0
  26. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/.github/workflows/publish-dev.yml +0 -0
  27. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/.github/workflows/publish-image.yml +0 -0
  28. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/.github/workflows/publish.yml +0 -0
  29. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/.github/workflows/version-parity.yml +0 -0
  30. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/.github/workflows/worker-image.yml +0 -0
  31. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/.gitignore +0 -0
  32. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/Dockerfile +0 -0
  33. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/LICENSE +0 -0
  34. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/README.md +0 -0
  35. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/build/kernel_cache/.gitignore +0 -0
  36. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/build/kernel_cache/.keep +0 -0
  37. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/docker/Dockerfile.kernelcache +0 -0
  38. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/docker/Dockerfile.kernelcache.relayer +0 -0
  39. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/docker/bake_kernel_cache.py +0 -0
  40. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/docker/bake_pod_entry.py +0 -0
  41. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/docker/kernel_fingerprint.py +0 -0
  42. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/docker/make_rp_handler.py +0 -0
  43. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/docs/cli-style/README.md +0 -0
  44. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/docs/cli-style/generate.py +0 -0
  45. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/docs/cli-style/index.html +0 -0
  46. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/docs/cli-style/preview.png +0 -0
  47. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/docs/cli-style/themed-errors.png +0 -0
  48. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/docs/cli-style/train-config-error-after.png +0 -0
  49. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/docs/cli-style/train-config-error-before.png +0 -0
  50. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/docs/kernel-cache.md +0 -0
  51. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/__init__.py +0 -0
  52. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/_channel.py +0 -0
  53. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/_fileio.py +0 -0
  54. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/_logging.py +0 -0
  55. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/_update_check.py +0 -0
  56. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/adapter_artifacts.py +0 -0
  57. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/catalog.py +0 -0
  58. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/cli/__main__.py +0 -0
  59. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/cli/_tty.py +0 -0
  60. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/cli/envpush.py +0 -0
  61. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/cli/training_doc.py +0 -0
  62. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/client/__init__.py +0 -0
  63. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/client/config.py +0 -0
  64. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/client/http.py +0 -0
  65. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/client/runtime_secrets.py +0 -0
  66. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/client/specs.py +0 -0
  67. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/cost/__init__.py +0 -0
  68. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/cost/analytical.py +0 -0
  69. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/cost/facts.py +0 -0
  70. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/cost/spec.py +0 -0
  71. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/cost/types.py +0 -0
  72. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/engine/__init__.py +0 -0
  73. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/engine/accounting.py +0 -0
  74. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/engine/chalk_kernels.py +0 -0
  75. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/engine/multiturn_rollout.py +0 -0
  76. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/engine/recipe.py +0 -0
  77. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/engine/vram.py +0 -0
  78. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/engine/worker/__main__.py +0 -0
  79. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/engine/worker/_pkg.py +0 -0
  80. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/engine/worker/adapter.py +0 -0
  81. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/engine/worker/decoding.py +0 -0
  82. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/engine/worker/finalize.py +0 -0
  83. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/engine/worker/gpu_setup.py +0 -0
  84. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/engine/worker/grpo.py +0 -0
  85. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/engine/worker/heartbeat.py +0 -0
  86. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/engine/worker/hf.py +0 -0
  87. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/engine/worker/lora.py +0 -0
  88. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/engine/worker/packing.py +0 -0
  89. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/engine/worker/perf/attn.py +0 -0
  90. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/engine/worker/perf/diagnostics.py +0 -0
  91. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/engine/worker/perf/lifecycle.py +0 -0
  92. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/engine/worker/perf/liger.py +0 -0
  93. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/engine/worker/perf/loraplus.py +0 -0
  94. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/engine/worker/perf/memory.py +0 -0
  95. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/engine/worker/rl.py +0 -0
  96. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/engine/worker/wandb_log.py +0 -0
  97. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/envs/__init__.py +0 -0
  98. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/envs/adapter.py +0 -0
  99. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/envs/archive_policy.py +0 -0
  100. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/envs/base.py +0 -0
  101. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/envs/loader.py +0 -0
  102. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/envs/pull.py +0 -0
  103. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/envs/registry.py +0 -0
  104. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/lora_rank.py +0 -0
  105. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/__init__.py +0 -0
  106. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/_auth.py +0 -0
  107. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/_hf_artifacts.py +0 -0
  108. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/_hf_retry.py +0 -0
  109. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/_http.py +0 -0
  110. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/_instance.py +0 -0
  111. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/_instance_bootstrap.py +0 -0
  112. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/_instance_poll.py +0 -0
  113. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/_instance_provider.py +0 -0
  114. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/_poll.py +0 -0
  115. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/allocator.py +0 -0
  116. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/base.py +0 -0
  117. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/lambdalabs/__init__.py +0 -0
  118. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/lambdalabs/api.py +0 -0
  119. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/lambdalabs/auth.py +0 -0
  120. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/lambdalabs/gpus.py +0 -0
  121. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/lambdalabs/jobs/__init__.py +0 -0
  122. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/lambdalabs/jobs/builders.py +0 -0
  123. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/lambdalabs/preflight.py +0 -0
  124. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/lambdalabs/pricing.py +0 -0
  125. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/preflight.py +0 -0
  126. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/realized.py +0 -0
  127. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/runpod/__init__.py +0 -0
  128. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/runpod/api.py +0 -0
  129. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/runpod/auth.py +0 -0
  130. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/runpod/cost.py +0 -0
  131. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/runpod/gpus.py +0 -0
  132. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/runpod/jobs.py +0 -0
  133. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/runpod/keys.py +0 -0
  134. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/runpod/preflight.py +0 -0
  135. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/runpod/preload.py +0 -0
  136. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/runpod/pricing.py +0 -0
  137. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/runpod/slots.py +0 -0
  138. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/runpod/train/__init__.py +0 -0
  139. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/runpod/train/deps.py +0 -0
  140. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/runpod/train/endpoints.py +0 -0
  141. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/vast/__init__.py +0 -0
  142. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/vast/api.py +0 -0
  143. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/vast/auth.py +0 -0
  144. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/vast/jobs/__init__.py +0 -0
  145. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/vast/jobs/builders.py +0 -0
  146. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/vast/preflight.py +0 -0
  147. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/providers/vast/pricing.py +0 -0
  148. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/py.typed +0 -0
  149. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/runner/__init__.py +0 -0
  150. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/runner/checkpoints.py +0 -0
  151. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/runner/deploy.py +0 -0
  152. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/runner/lifecycle.py +0 -0
  153. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/schema/__init__.py +0 -0
  154. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/schema/fields.py +0 -0
  155. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/serve/__init__.py +0 -0
  156. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/serve/deploy.py +0 -0
  157. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/serve/export.py +0 -0
  158. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/serve/pricing.py +0 -0
  159. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/server/__init__.py +0 -0
  160. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/server/__main__.py +0 -0
  161. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/server/_deps.py +0 -0
  162. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/server/_internal_client.py +0 -0
  163. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/server/_locks.py +0 -0
  164. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/server/_runtime.py +0 -0
  165. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/server/app.py +0 -0
  166. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/server/auth.py +0 -0
  167. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/server/billing.py +0 -0
  168. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/server/billing_retry.py +0 -0
  169. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/server/checkpoints.py +0 -0
  170. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/server/db.py +0 -0
  171. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/server/environment_registry.py +0 -0
  172. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/server/envs.py +0 -0
  173. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/server/reconcile.py +0 -0
  174. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/server/routes/__init__.py +0 -0
  175. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/server/routes/envs.py +0 -0
  176. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/server/routes/meta.py +0 -0
  177. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/server/routes/runs.py +0 -0
  178. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/server/routes/serving.py +0 -0
  179. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/server/run_registry.py +0 -0
  180. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/flash/spec.py +0 -0
  181. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/infisical-entrypoint.sh +0 -0
  182. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/scripts/build_dev_dist.py +0 -0
  183. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/__init__.py +0 -0
  184. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/_helpers/__init__.py +0 -0
  185. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/_helpers/runner.py +0 -0
  186. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/_helpers/specs.py +0 -0
  187. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/_helpers/vast.py +0 -0
  188. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/conftest.py +0 -0
  189. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/fixtures/math_eval.jsonl +0 -0
  190. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/fixtures/math_train.jsonl +0 -0
  191. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/live/__init__.py +0 -0
  192. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/live/conftest.py +0 -0
  193. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/live/test_lambda_live.py +0 -0
  194. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/live/test_runpod_live.py +0 -0
  195. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/live/test_vast_live.py +0 -0
  196. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_agent_flash_cli_contract.py +0 -0
  197. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_algorithms.py +0 -0
  198. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_allocator.py +0 -0
  199. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_b200_rollout_opt.py +0 -0
  200. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_backend_jobspec_contract.py +0 -0
  201. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_billing_retry.py +0 -0
  202. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_cancel_remote.py +0 -0
  203. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_catalog_consistency.py +0 -0
  204. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_chalk_kernels.py +0 -0
  205. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_charge_pricing.py +0 -0
  206. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_checkpoints.py +0 -0
  207. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_cli_errors.py +0 -0
  208. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_cli_estimate.py +0 -0
  209. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_cli_help.py +0 -0
  210. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_cli_managed.py +0 -0
  211. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_cli_render_theme.py +0 -0
  212. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_client.py +0 -0
  213. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_client_server_integration.py +0 -0
  214. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_config_overrides.py +0 -0
  215. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_cost_analytical.py +0 -0
  216. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_cost_equation.py +0 -0
  217. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_cost_estimate.py +0 -0
  218. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_cost_hardware.py +0 -0
  219. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_cost_models.py +0 -0
  220. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_cost_rewards.py +0 -0
  221. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_dev_channel.py +0 -0
  222. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_disk_gb.py +0 -0
  223. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_endpoint_name.py +0 -0
  224. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_env_cache_evict.py +0 -0
  225. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_env_delete.py +0 -0
  226. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_env_download.py +0 -0
  227. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_env_download_api.py +0 -0
  228. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_env_no_install.py +0 -0
  229. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_env_publish.py +0 -0
  230. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_env_pull.py +0 -0
  231. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_env_pull_managed_control_plane.py +0 -0
  232. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_env_push.py +0 -0
  233. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_env_rate_limit_resolve.py +0 -0
  234. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_envs_coverage.py +0 -0
  235. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_export.py +0 -0
  236. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_flash_mvp.py +0 -0
  237. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_flashinfer_cache_dirs.py +0 -0
  238. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_github_urlopen_retry.py +0 -0
  239. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_gpus.py +0 -0
  240. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_grpo_mask_aware.py +0 -0
  241. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_grpo_params.py +0 -0
  242. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_grpo_sleep_gate.py +0 -0
  243. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_health_liveness.py +0 -0
  244. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_idle_endpoint_reaper.py +0 -0
  245. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_internal_client.py +0 -0
  246. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_jobs.py +0 -0
  247. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_kernel_cache.py +0 -0
  248. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_kernel_fingerprint.py +0 -0
  249. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_kv_util.py +0 -0
  250. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_lambda_runner.py +0 -0
  251. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_logging.py +0 -0
  252. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_login_perms.py +0 -0
  253. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_lora_rank_preflight.py +0 -0
  254. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_managed_hf_repo.py +0 -0
  255. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_metrics_schema_agent_contract.py +0 -0
  256. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_mig_guard.py +0 -0
  257. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_multiturn_rollout.py +0 -0
  258. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_oom_escalate_gpu.py +0 -0
  259. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_open_model_policy.py +0 -0
  260. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_orchestrator_flash.py +0 -0
  261. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_packing.py +0 -0
  262. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_poll_helpers.py +0 -0
  263. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_preflight.py +0 -0
  264. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_provider_routing.py +0 -0
  265. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_provider_teardown_robustness.py +0 -0
  266. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_providers_symmetry.py +0 -0
  267. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_realized_cost.py +0 -0
  268. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_resolve_params_b.py +0 -0
  269. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_resume_on_retry.py +0 -0
  270. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_runmgmt.py +0 -0
  271. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_runpod_api_delete.py +0 -0
  272. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_runpod_key_fingerprint.py +0 -0
  273. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_runpod_key_waterfall.py +0 -0
  274. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_runpod_slots.py +0 -0
  275. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_serve.py +0 -0
  276. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_server_api.py +0 -0
  277. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_server_billing.py +0 -0
  278. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_server_db.py +0 -0
  279. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_serving_contract.py +0 -0
  280. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_sft_gc_off.py +0 -0
  281. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_spec_and_validation.py +0 -0
  282. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_thinking_config.py +0 -0
  283. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_train_context_preflight.py +0 -0
  284. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_update_check.py +0 -0
  285. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_vast_api.py +0 -0
  286. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_vast_offers.py +0 -0
  287. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_vast_runner.py +0 -0
  288. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_verifiers.py +0 -0
  289. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_version.py +0 -0
  290. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_vl_warmstart_adapter_keys.py +0 -0
  291. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_vl_warmstart_recombine.py +0 -0
  292. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_vl_weight_sync.py +0 -0
  293. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_wandb_naming.py +0 -0
  294. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_warmstart_cross_repo.py +0 -0
  295. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_weight_cache.py +0 -0
  296. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_worker_dryrun.py +0 -0
  297. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_worker_hardexit.py +0 -0
  298. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_worker_image.py +0 -0
  299. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_worker_init_heartbeat.py +0 -0
  300. {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.43}/tests/test_worker_thinking.py +0 -0
@@ -69,7 +69,12 @@ RUN pip install --no-cache-dir \
69
69
  # miscomputed with Triton>=3.4 (fla #640) — the fix is fla's TILELANG backend (correct there), so
70
70
  # we bake the pinned tilelang==0.1.11 + apache-tvm-ffi==0.1.11 (0.1.12 double-registers TVM-FFI ->
71
71
  # `import tilelang` aborts) and KEEP fla on every arch; flash.engine.worker._ensure_fla_fastpath_on_hopper
72
- # ensures the tilelang backend is live on sm90 before any model import. Validated win vs the old
72
+ # ensures the tilelang backend is live on sm90 before any model import. The INVERSE holds on
73
+ # B200/sm100: THERE the tilelang chunk_bwd_dqkwg miscomputes gradients while the Triton path is
74
+ # correct — and the pinned fla default-enables tilelang wherever it imports (i.e. everywhere,
75
+ # since it is baked here for Hopper), so the worker opts sm100 out via FLA_TILELANG=0
76
+ # (engine.worker.perf._force_fla_triton_gdn_on_sm100; upstream default-gates tilelang to
77
+ # Hopper-only since fla #975). Validated win vs the old
73
78
  # pure-PyTorch fallback (H100 SXM, Qwen3.5 hidden-2560 LoRA): seq4096 4.2x faster / 1.6x less mem,
74
79
  # seq16384 12.6x / 1.9x, loss matches to 1.8e-4. fla is from git: the PyPI wheel is a broken stub
75
80
  # (no fla.modules). The git URL is PINNED to a commit (not the moving default branch) for
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: freesolo-flash-dev
3
- Version: 0.2.41
3
+ Version: 0.2.43
4
4
  Summary: Flash — managed LoRA post-training (SFT/GRPO) 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
@@ -249,7 +249,31 @@ def _build_parser() -> argparse.ArgumentParser:
249
249
  const="multi",
250
250
  help="scaffold a multi-turn environment (bounded episode with step_episode / score_episode).",
251
251
  )
252
- setup.set_defaults(func=cmd_env_setup, turn_mode="single")
252
+ setup_reason = setup.add_mutually_exclusive_group()
253
+ setup_reason.add_argument(
254
+ "--reasoning",
255
+ dest="reasoning",
256
+ action="store_const",
257
+ const=True,
258
+ help="scaffold configs with reasoning enabled (thinking = true, with a raised token budget).",
259
+ )
260
+ setup_reason.add_argument(
261
+ "--no-reasoning",
262
+ dest="reasoning",
263
+ action="store_const",
264
+ const=False,
265
+ help="scaffold configs without reasoning. This is the default.",
266
+ )
267
+ setup.add_argument(
268
+ "-y",
269
+ "--yes",
270
+ dest="yes",
271
+ action="store_true",
272
+ help="accept defaults without prompting (single-turn, no reasoning).",
273
+ )
274
+ # turn_mode / reasoning default to None (unset) so the scaffold can tell an explicit flag
275
+ # apart from "not chosen yet" and, on an interactive terminal, ask instead of assuming.
276
+ setup.set_defaults(func=cmd_env_setup, turn_mode=None, reasoning=None, yes=False)
253
277
 
254
278
  env_list = env_sub.add_parser("list", help="list local environment sources")
255
279
  env_list.set_defaults(func=cmd_env_list)
@@ -330,14 +330,40 @@ _STARTER_DATASET_MULTITURN_JSONL = """\
330
330
  """
331
331
 
332
332
 
333
+ _TURN_OPTIONS = [
334
+ ("single", "single-turn", "one prompt -> one response"),
335
+ ("multi", "multi-turn", "bounded episode: step_episode / score_episode"),
336
+ ]
337
+ _REASONING_OPTIONS = [
338
+ ("off", "no reasoning", "the model answers directly"),
339
+ ("on", "reasoning", "thinking = true; spends more tokens per answer"),
340
+ ]
341
+
342
+
343
+ def _setup_interactive(args) -> bool:
344
+ """Whether to ask the setup questions interactively.
345
+
346
+ Prompt only on a real terminal a human can answer from. Fall back to defaults (no prompt) when
347
+ --yes is passed, under CI, or when stdin is closed/redirected, so automation never blocks on an
348
+ unanswered prompt. A pseudo-TTY in CI can report isatty()=True, so CI is checked explicitly; a
349
+ closed fd 0 can make sys.stdin None, so that is guarded before .isatty()."""
350
+ if getattr(args, "yes", False):
351
+ return False
352
+ if os.environ.get("CI", "").strip().lower() not in ("", "0", "false", "no"):
353
+ return False
354
+ stdin = sys.stdin
355
+ if stdin is None or not stdin.isatty():
356
+ return False
357
+ return render.styled()
358
+
359
+
333
360
  def cmd_env_setup(args) -> int:
334
- requested_multi = getattr(args, "turn_mode", "single") == "multi"
335
361
  starter_env = Path("environment.py")
336
362
  dataset = Path("dataset/train.jsonl")
337
363
  # An existing environment.py is the authoritative signal for which turn mode this
338
364
  # scaffold already uses (the dataset is plain JSONL with no reliable mode marker).
339
365
  # Anchor to it so a re-run never leaves a single-turn env beside a multi-turn
340
- # dataset (or vice versa); the flag only decides the mode when starting fresh.
366
+ # dataset (or vice versa); the flag/answer only decides the mode when starting fresh.
341
367
  existing_multi: bool | None = None
342
368
  anchor = "environment.py"
343
369
  if starter_env.exists():
@@ -347,15 +373,59 @@ def cmd_env_setup(args) -> int:
347
373
  # distinctive prompt; use it so we don't drop a single-turn env beside it.
348
374
  existing_multi = "secret whole number" in dataset.read_text(encoding="utf-8")
349
375
  anchor = "dataset/train.jsonl"
350
- if existing_multi is not None and existing_multi != requested_multi:
351
- have = "multi-turn" if existing_multi else "single-turn"
352
- want = "multi-turn" if requested_multi else "single-turn"
353
- msg = (
354
- f"existing {anchor} is {have}; keeping it and ignoring --{want}. "
355
- f"Delete environment.py and dataset/train.jsonl first to re-scaffold as {want}."
376
+
377
+ # Resolve the turn mode. An existing scaffold wins (warn if a flag disagrees); otherwise an
378
+ # explicit --single-turn/--multi-turn flag wins; otherwise ask on a terminal, else single-turn.
379
+ flag_mode = getattr(args, "turn_mode", None)
380
+ if existing_multi is not None:
381
+ if flag_mode is not None and (flag_mode == "multi") != existing_multi:
382
+ have = "multi-turn" if existing_multi else "single-turn"
383
+ want = "multi-turn" if flag_mode == "multi" else "single-turn"
384
+ msg = (
385
+ f"existing {anchor} is {have}; keeping it and ignoring --{want}. "
386
+ f"Delete environment.py and dataset/train.jsonl first to re-scaffold as {want}."
387
+ )
388
+ print(render.warn(msg) if render.styled() else f"warning: {msg}", file=sys.stderr)
389
+ multi_turn = existing_multi
390
+ elif flag_mode is not None:
391
+ multi_turn = flag_mode == "multi"
392
+ elif _setup_interactive(args):
393
+ multi_turn = (
394
+ render.select("How does the model interact with your task?", _TURN_OPTIONS) == "multi"
356
395
  )
357
- print(render.warn(msg) if render.styled() else f"warning: {msg}", file=sys.stderr)
358
- multi_turn = requested_multi if existing_multi is None else existing_multi
396
+ else:
397
+ multi_turn = False
398
+
399
+ # Resolve reasoning. Like the turn mode, an existing config is authoritative: configs are only
400
+ # written when absent, so applying a reasoning flag to an already-scaffolded project would
401
+ # silently no-op (or write one config with reasoning and leave the other without). Anchor to the
402
+ # existing config's `thinking` state and warn if a flag disagrees; otherwise the flag wins;
403
+ # otherwise ask on a terminal; else off.
404
+ rl = Path("configs/rl.toml")
405
+ sft = Path("configs/sft.toml")
406
+ existing_reasoning: bool | None = None
407
+ for cfg in (rl, sft):
408
+ if cfg.exists():
409
+ existing_reasoning = "thinking = true" in cfg.read_text(encoding="utf-8")
410
+ break
411
+ flag_reason = getattr(args, "reasoning", None)
412
+ if existing_reasoning is not None:
413
+ if flag_reason is not None and flag_reason != existing_reasoning:
414
+ have = "reasoning" if existing_reasoning else "no reasoning"
415
+ want = "reasoning" if flag_reason else "no-reasoning"
416
+ msg = (
417
+ f"existing configs are {have}; keeping them and ignoring --{want}. "
418
+ f"Delete configs/rl.toml and configs/sft.toml first to re-scaffold with --{want}."
419
+ )
420
+ print(render.warn(msg) if render.styled() else f"warning: {msg}", file=sys.stderr)
421
+ reasoning = existing_reasoning
422
+ elif flag_reason is not None:
423
+ reasoning = flag_reason
424
+ elif _setup_interactive(args):
425
+ reasoning = render.select("Train with reasoning (thinking)?", _REASONING_OPTIONS) == "on"
426
+ else:
427
+ reasoning = False
428
+
359
429
  env_py = _STARTER_ENV_MULTITURN_PY if multi_turn else _STARTER_ENV_PY
360
430
  dataset_jsonl = _STARTER_DATASET_MULTITURN_JSONL if multi_turn else _STARTER_DATASET_JSONL
361
431
  Path("configs").mkdir(exist_ok=True)
@@ -373,28 +443,47 @@ def cmd_env_setup(args) -> int:
373
443
  'id = ""\n\n'
374
444
  '# secrets = ["SERPAPI_API_KEY"]\n\n'
375
445
  )
376
- rl = Path("configs/rl.toml")
446
+ # `thinking = true` opts the run into reasoning mode. Reasoning shares the generation budget with
447
+ # the answer, so GRPO also gets a raised max_tokens. These strings are empty when reasoning is
448
+ # off, keeping the default scaffold byte-for-byte identical.
449
+ thinking_line = "thinking = true\n" if reasoning else ""
450
+ rl_reasoning_train = (
451
+ "max_tokens = 2048 # reasoning shares this budget with the answer; raised so it isn't truncated\n"
452
+ if reasoning
453
+ else ""
454
+ )
455
+ sft_reasoning_note = (
456
+ "# reasoning is on (thinking = true): each gold `output` must contain a <think>...</think>\n"
457
+ "# block; validate locally with freesolo.datasets.warn_missing_think_tags before a real run.\n"
458
+ if reasoning
459
+ else ""
460
+ )
377
461
  if not rl.exists():
378
462
  rl.write_text(
379
463
  'model = "Qwen/Qwen3.5-4B"\n'
380
- 'algorithm = "grpo"\n\n'
464
+ 'algorithm = "grpo"\n'
465
+ f"{thinking_line}"
466
+ "\n"
381
467
  f"{env_comment}"
382
468
  "[train]\n"
383
469
  "steps = 150\n"
470
+ f"{rl_reasoning_train}"
384
471
  "lora_rank = 32\n"
385
472
  "# GPU and HF artifacts are managed automatically by the platform: the GPU is\n"
386
473
  "# the cheapest fitting managed class, and artifacts live in a private environment-scoped repo.\n"
387
474
  )
388
- sft = Path("configs/sft.toml")
389
475
  if not sft.exists():
390
476
  sft.write_text(
391
477
  'model = "Qwen/Qwen3.5-4B"\n'
392
- 'algorithm = "sft"\n\n'
478
+ 'algorithm = "sft"\n'
479
+ f"{thinking_line}"
480
+ "\n"
393
481
  f"{env_comment}"
394
482
  "[train]\n"
395
483
  "epochs = 1\n"
396
484
  "max_examples = 2 # rows to train on; the starter dataset has 2 (raise as your dataset grows)\n"
397
485
  "lora_rank = 32\n"
486
+ f"{sft_reasoning_note}"
398
487
  "# GPU and HF artifacts are managed automatically by the platform: the GPU is\n"
399
488
  "# the cheapest fitting managed class, and artifacts live in a private environment-scoped repo.\n"
400
489
  )
@@ -768,7 +857,9 @@ def cmd_deploy(args) -> int:
768
857
  f"OpenAI-compatible base URL: {openai_base} — point clients at this /v1 base, "
769
858
  "not the bare endpoint (which 404s on /chat/completions)."
770
859
  )
771
- print(render.arrow(url_note) if render.styled() else f"note: {url_note}", file=sys.stderr)
860
+ print(
861
+ render.arrow(url_note) if render.styled() else f"note: {url_note}", file=sys.stderr
862
+ )
772
863
  if dep.get("state") != "dry_run":
773
864
  state = dep.get("state", "deploying")
774
865
  if state == "failed":
@@ -273,6 +273,38 @@ def arrow(msg: str) -> str:
273
273
  return _safe(f"{_paint(_glyph('→', '->'), _ACCENT2)} {_dim(msg)}")
274
274
 
275
275
 
276
+ def select(title: str, options: list[tuple[str, str, str]], default: int = 0) -> str:
277
+ """Themed single-choice prompt; returns the chosen option's value.
278
+
279
+ ``options`` is a list of ``(value, label, hint)``. The default option is marked and taken on
280
+ an empty answer (enter). Reads via ``input()`` so it is easy to drive in tests; the caller
281
+ decides *when* to prompt (interactive stdin), so this always prompts when called. On EOF the
282
+ default is returned so a closed stdin never hangs the scaffold."""
283
+ q = _paint(_glyph("?", "?"), _ACCENT, "1")
284
+ print(f"{q} {_bold(_safe(title))}")
285
+ for i, (_value, label, hint) in enumerate(options):
286
+ num = _paint(f"{i + 1})", _ACCENT2)
287
+ lab = _bold(label) if i == default else label
288
+ tail = f" {_dim(_safe(hint))}" if hint else ""
289
+ mark = _paint(" (default)", _GREEN) if i == default else ""
290
+ print(f" {num} {_safe(lab)}{tail}{mark}")
291
+ pointer = _paint(_glyph("›", ">"), _ACCENT2) # noqa: RUF001 (the glyph is the point)
292
+ for _ in range(5):
293
+ try:
294
+ raw = input(f"{pointer} ").strip()
295
+ except EOFError:
296
+ print()
297
+ return options[default][0]
298
+ if not raw:
299
+ return options[default][0]
300
+ if raw.isdigit():
301
+ idx = int(raw) - 1
302
+ if 0 <= idx < len(options):
303
+ return options[idx][0]
304
+ print(note(f"enter 1-{len(options)}, or press enter for the default"))
305
+ return options[default][0]
306
+
307
+
276
308
  def money(value: float, decimals: int = 4) -> str:
277
309
  return _paint(f"${value:.{decimals}f}", _TEAL)
278
310
 
@@ -100,6 +100,7 @@ from flash.engine.worker.perf import (
100
100
  _estimate_params,
101
101
  _flash_attn_3_available,
102
102
  _flash_attn_available,
103
+ _force_fla_triton_gdn_on_sm100,
103
104
  _GpuPeakSampler,
104
105
  _liger_default_for_model,
105
106
  _memory_mode,
@@ -108,6 +109,7 @@ from flash.engine.worker.perf import (
108
109
  _peak_gpu_gb,
109
110
  _remove_fla_from_disk,
110
111
  _reset_peak_gpu,
112
+ _restrict_fla_gdn_autotune_on_blackwell,
111
113
  _sdpa_cudnn_ctx,
112
114
  free_gpu,
113
115
  fused_optim_name,
@@ -265,9 +267,15 @@ def main():
265
267
  raise RetriableInfraError(
266
268
  f"DONE present but metrics.json unreadable after retries (transient HF): {last_err}"
267
269
  )
270
+ # BEFORE any model import / fla dispatch: on sm100 the baked tilelang GDN backend
271
+ # computes wrong gradients — opt out so fla uses its (correct-there) Triton path.
272
+ _force_fla_triton_gdn_on_sm100()
268
273
  _ensure_fla_fastpath_on_hopper()
269
274
  # Must run AFTER fla fast path (may reinstall tilelang) and BEFORE model/vLLM import.
270
275
  _neutralize_tilelang_cudart_stub()
276
+ # AFTER the fla fast path (which may (re)install fla), BEFORE any model import / GDN
277
+ # launch: restrict fla's Blackwell GDN bwd autotune to grad-correct configs (fla #913).
278
+ _restrict_fla_gdn_autotune_on_blackwell()
271
279
  heartbeat("boot", gpu=gpu_diagnostics(include_torch=False))
272
280
  finalize_alloc_conf_for_sleep()
273
281
  load_mega_cache()
@@ -344,6 +352,7 @@ __all__ = [
344
352
  "_finalize",
345
353
  "_flash_attn_3_available",
346
354
  "_flash_attn_available",
355
+ "_force_fla_triton_gdn_on_sm100",
347
356
  "_grpo_is_no_op_failure",
348
357
  "_grpo_resume_already_complete",
349
358
  "_hf_upload",
@@ -359,6 +368,7 @@ __all__ = [
359
368
  "_remove_fla_from_disk",
360
369
  "_reset_peak_gpu",
361
370
  "_resolve_adapter_ref",
371
+ "_restrict_fla_gdn_autotune_on_blackwell",
362
372
  "_sdpa_cudnn_ctx",
363
373
  "assert_adapter_delta_nonzero",
364
374
  "assert_adapter_load_clean",
@@ -77,7 +77,9 @@ def _require_gpu():
77
77
  if not torch.cuda.is_available():
78
78
  _log("no CUDA device visible — kernel warmup must run on a GPU builder; nothing baked")
79
79
  return None
80
- _log(f"GPU: {torch.cuda.get_device_name(0)} ({_torch_sm(torch)}), torch {torch.__version__}")
80
+ _log(
81
+ f"GPU: {torch.cuda.get_device_name(0)} ({_torch_sm(torch)}), torch {torch.__version__}"
82
+ )
81
83
  return torch
82
84
  except Exception as e:
83
85
  _log(f"torch unavailable ({e}); cannot warm kernels")
@@ -128,6 +130,13 @@ def warm_flash_attn(torch) -> bool:
128
130
  def warm_fla_gdn(torch) -> bool:
129
131
  """Compile flash-linear-attention's Gated-DeltaNet chunk kernels (Qwen3.5/3.6 hybrid path)."""
130
132
  try:
133
+ # sm100: tilelang's GDN bwd miscomputes grads — warm the Triton path the worker will run.
134
+ try:
135
+ from flash.engine.worker.perf import _force_fla_triton_gdn_on_sm100
136
+
137
+ _force_fla_triton_gdn_on_sm100()
138
+ except Exception as e:
139
+ _log(f"sm100 fla tilelang opt-out skipped: {e}")
131
140
  # fla #640: GDN chunk_bwd needs tilelang on Hopper; Triton path miscomputes/raises there.
132
141
  try:
133
142
  from flash.engine.worker.perf import _ensure_fla_fastpath_on_hopper
@@ -135,6 +144,14 @@ def warm_fla_gdn(torch) -> bool:
135
144
  _ensure_fla_fastpath_on_hopper()
136
145
  except Exception as e:
137
146
  _log(f"hopper fla fast-path setup skipped: {e}")
147
+ # fla #913: on Blackwell, warm the SAME restricted autotune space the worker boot will
148
+ # run (grad-correct configs only) so the baked cache holds the config that actually runs.
149
+ try:
150
+ from flash.engine.worker.perf import _restrict_fla_gdn_autotune_on_blackwell
151
+
152
+ _restrict_fla_gdn_autotune_on_blackwell()
153
+ except Exception as e:
154
+ _log(f"blackwell fla autotune restriction skipped: {e}")
138
155
  from fla.ops.gated_delta_rule import chunk_gated_delta_rule
139
156
 
140
157
  b, h, t, d = 1, 4, 256, 64
@@ -131,7 +131,7 @@ def _find_real_libcudart() -> str | None:
131
131
  with open("/proc/self/maps") as f:
132
132
  for line in f:
133
133
  if base in line and "/" in line:
134
- p = line[line.index("/"):].rstrip()
134
+ p = line[line.index("/") :].rstrip()
135
135
  if os.path.basename(p).startswith(base) and os.path.exists(p):
136
136
  return os.path.realpath(p)
137
137
  except OSError:
@@ -208,6 +208,138 @@ def _neutralize_tilelang_cudart_stub() -> None:
208
208
  print(f"[worker] libcudart stub neutralize failed: {e}", flush=True)
209
209
 
210
210
 
211
+ def _force_fla_triton_gdn_on_sm100() -> None:
212
+ """Opt fla OUT of its tilelang GDN backend on B200 (sm100) via ``FLA_TILELANG=0``.
213
+
214
+ The worker image bakes tilelang for the HOPPER fast path (fla #640), but the pinned fla
215
+ default-enables its tilelang backend WHEREVER tilelang imports. On sm100, tilelang's
216
+ ``chunk_bwd_dqkwg`` computes WRONG GRADIENTS — measured on a real B200 with this exact image
217
+ at the production Qwen3.5/3.6 GDN call shapes (H==HV after transformers' head repeat):
218
+ dq/dk rel-err ~0.72, dg ~1.28 vs the fp32 reference, deterministic, in bf16 AND fp32, while
219
+ the same shapes on H200 are correct to ~4e-3. This is the root cause of the B200 35B-A3B SFT
220
+ incident (grad_norm ~1e8 from the first logged step; loss flat at LR 2e-5/5e-5, collapse at
221
+ 1e-4 — garbage gradient DIRECTIONS no LR can fix, while H200 trained healthily at 1e-4).
222
+
223
+ ``FLA_TILELANG=0`` flips fla's dispatch to its Triton chunk_bwd_dqkwg — verified correct on
224
+ sm100 at the same shapes (~4e-3). Upstream has since stopped default-enabling tilelang
225
+ off-Hopper (fla #975 gates the default to sm90 + Triton>=3.4) and an explicit env opt-out
226
+ wins on every fla version, so this env set reproduces upstream's current gate on our pin and
227
+ stays a correct no-op across a future pin bump.
228
+
229
+ * ``setdefault``: an explicitly pre-set FLA_TILELANG (e.g. testing a fixed tilelang) wins.
230
+ * sm100 only: sm90 NEEDS tilelang (fla #640, the fast-path installer owns it); sm89/sm120
231
+ train healthily today under the pin's default and upstream's next-pin gate flips them to
232
+ Triton anyway — no evidence to justify changing them from here.
233
+ * Env is read live per-dispatch by fla, but set it at boot BEFORE any model import so no
234
+ kernel ever launches under the old default.
235
+ """
236
+ try:
237
+ import torch
238
+
239
+ if not (torch.cuda.is_available() and torch.cuda.get_device_capability() == (10, 0)):
240
+ return
241
+ except Exception:
242
+ return
243
+ prior = os.environ.get("FLA_TILELANG")
244
+ if prior is not None:
245
+ print(
246
+ f"[blackwell] FLA_TILELANG={prior!r} pre-set; respecting it "
247
+ "(default here is 0 on sm100: tilelang chunk_bwd_dqkwg miscomputes grads)",
248
+ flush=True,
249
+ )
250
+ return
251
+ os.environ["FLA_TILELANG"] = "0"
252
+ print(
253
+ "[blackwell] sm100 (B200): FLA_TILELANG=0 -> fla GDN uses the Triton chunk_bwd_dqkwg "
254
+ "(tilelang backend computes wrong gradients on sm100; measured dq/dk ~0.72, dg ~1.28 "
255
+ "rel-err; upstream default-gates tilelang to Hopper since fla #975)",
256
+ flush=True,
257
+ )
258
+
259
+
260
+ def _restrict_fla_gdn_autotune_on_blackwell() -> None:
261
+ """Restrict fla's GDN ``prepare_wy_repr_bwd_kernel`` autotune space on Blackwell (sm100/sm120).
262
+
263
+ Defense-in-depth for the Triton GDN backward path — the path sm100 defaults to once
264
+ ``_force_fla_triton_gdn_on_sm100`` opts out of tilelang. Upstream reports that Blackwell can
265
+ select unstable Triton configs for this kernel during autotuning (fla #913) and restricted
266
+ the space to the B200-validated config (num_warps=2, num_stages=4) in fla #1000 (ac6c648) —
267
+ NEWER than the worker's pinned fla SHA — so apply the same restriction in-process at boot,
268
+ before any GDN kernel launch. (Not the 35B-A3B incident root cause — that was tilelang, see
269
+ above — but there is no reason to keep autotuning over configs upstream deemed unstable on
270
+ the exact card we train on.)
271
+
272
+ * No-op on non-Blackwell arches, when fla is absent (pure-PyTorch delta path), or when the
273
+ pinned fla already carries the upstream fix (filtering an already-restricted space).
274
+ * Fail-CLOSED like the Hopper fast path: if fla is present on Blackwell but the restriction
275
+ cannot be applied (autotuner layout changed — e.g. an unreviewed pin bump), physically
276
+ remove fla so transformers falls back to the pure-PyTorch delta rule. Slow-but-correct
277
+ beats a run that burns GPU-hours computing garbage gradients.
278
+ * sm120 is included to match upstream's IS_NVIDIA_BLACKWELL gate: 5090 smokes trained fine on
279
+ the unrestricted space, but that is autotune luck (the winning config varies per shape/run),
280
+ not evidence of safety.
281
+ """
282
+ try:
283
+ import torch
284
+
285
+ if not (torch.cuda.is_available() and torch.cuda.get_device_capability()[0] in (10, 12)):
286
+ return
287
+ except Exception:
288
+ return
289
+ try:
290
+ import importlib.util
291
+
292
+ if importlib.util.find_spec("fla") is None:
293
+ return # no fla -> transformers already uses the pure-PyTorch delta path
294
+ except Exception:
295
+ return
296
+
297
+ def _fail_closed(reason: str) -> None:
298
+ _removed, _still = _remove_fla_from_disk()
299
+ print(
300
+ f"[blackwell] fla GDN autotune restriction FAILED ({reason}) -> DISABLING fla "
301
+ f"(removed {len(_removed)} copy(ies); still_importable={_still}); "
302
+ "pure-PyTorch delta fallback (fla #913: unrestricted autotune miscomputes grads)",
303
+ flush=True,
304
+ )
305
+
306
+ try:
307
+ from fla.ops.gated_delta_rule import wy_fast
308
+
309
+ tuner = getattr(wy_fast, "prepare_wy_repr_bwd_kernel", None)
310
+ for _ in range(8): # unwrap decorator layers (heuristics/cache) down to the Autotuner
311
+ if tuner is None or hasattr(tuner, "configs"):
312
+ break
313
+ tuner = getattr(tuner, "fn", None)
314
+ configs = getattr(tuner, "configs", None)
315
+ if not configs:
316
+ _fail_closed("prepare_wy_repr_bwd_kernel autotuner not found")
317
+ return
318
+ keep = [
319
+ c
320
+ for c in configs
321
+ if getattr(c, "num_warps", None) == 2 and getattr(c, "num_stages", None) == 4
322
+ ]
323
+ if not keep:
324
+ _fail_closed("no B200-validated config (num_warps=2/num_stages=4) in autotune space")
325
+ return
326
+ if len(keep) == len(configs):
327
+ print(
328
+ "[blackwell] fla GDN autotune already restricted (pinned fla carries fla #1000)",
329
+ flush=True,
330
+ )
331
+ return
332
+ tuner.configs = keep
333
+ print(
334
+ f"[blackwell] fla GDN prepare_wy_repr_bwd autotune restricted {len(configs)} -> "
335
+ f"{len(keep)} config(s) (num_warps=2/num_stages=4; fla #913/#1000 grad miscompute)",
336
+ flush=True,
337
+ )
338
+ except Exception as e:
339
+ with contextlib.suppress(Exception):
340
+ _fail_closed(f"{type(e).__name__}: {e}")
341
+
342
+
211
343
  def _ensure_fla_fastpath_on_hopper() -> None:
212
344
  """Enable fla's tilelang GDN backend on Hopper (sm90); no-op elsewhere.
213
345
 
@@ -334,6 +466,7 @@ __all__ = [
334
466
  "_flash_attn_3_available",
335
467
  "_flash_attn_available",
336
468
  "_float_or_none",
469
+ "_force_fla_triton_gdn_on_sm100",
337
470
  "_int_or_none",
338
471
  "_liger_default_for_model",
339
472
  "_memory_mode",
@@ -344,6 +477,7 @@ __all__ = [
344
477
  "_query_nvidia_processes",
345
478
  "_remove_fla_from_disk",
346
479
  "_reset_peak_gpu",
480
+ "_restrict_fla_gdn_autotune_on_blackwell",
347
481
  "_round_gb_from_mib",
348
482
  "_sdpa_cudnn_ctx",
349
483
  "free_gpu",
@@ -99,6 +99,21 @@ def _model_arch_dims(model_id: str) -> tuple[int, int]:
99
99
  return c_hidden, c_layers
100
100
 
101
101
 
102
+ def select_sft_examples(train, max_examples, seed):
103
+ """Pick the SFT sample: the first ``max_examples`` rows of the dataset (file order), shuffled.
104
+
105
+ The slice happens BEFORE the shuffle so ``max_examples`` is a deterministic prefix fence,
106
+ not a random subsample. A train.jsonl that carries fully-labeled SFT rows first and
107
+ prompt-only (empty-output) GRPO rows after can cap SFT to the labeled head — an empty
108
+ completion can never be shuffled into the SFT sample and teach the model to emit nothing.
109
+ """
110
+ if max_examples > 0:
111
+ train = train[:max_examples]
112
+ rng = random.Random(seed)
113
+ rng.shuffle(train)
114
+ return train
115
+
116
+
102
117
  def run_sft():
103
118
  from datasets import Dataset
104
119
  from transformers import AutoTokenizer
@@ -122,12 +137,7 @@ def run_sft():
122
137
  val = getattr(_t, name, None) if _t else None
123
138
  return val if val is not None else default
124
139
 
125
- train = env.dataset()
126
- rng = random.Random(_w.SEED)
127
- rng.shuffle(train)
128
- max_examples = int(_train_opt("max_examples", 0) or 0)
129
- if max_examples > 0:
130
- train = train[:max_examples]
140
+ train = select_sft_examples(env.dataset(), int(_train_opt("max_examples", 0) or 0), _w.SEED)
131
141
  texts = []
132
142
  multiturn_targets = 0
133
143
  for ex in train:
@@ -41,7 +41,9 @@ WORKER_DEPS = [
41
41
  "wandb>=0.17",
42
42
  # fla from git: PyPI wheel is a broken stub missing fla.modules. SHA-pinned for reproducibility;
43
43
  # keep in lockstep with Dockerfile.worker. fla kept on ALL arches — worker ensures tilelang
44
- # backend on sm90 before model import (fla #640: chunk_bwd miscompute with Triton>=3.4 on Hopper).
44
+ # backend on sm90 before model import (fla #640: chunk_bwd miscompute with Triton>=3.4 on Hopper)
45
+ # and OPTS OUT of tilelang on sm100 (B200) where tilelang's chunk_bwd_dqkwg miscomputes grads
46
+ # (worker _force_fla_triton_gdn_on_sm100; upstream default-gates tilelang to Hopper since fla #975).
45
47
  "flash-linear-attention @ git+https://github.com/fla-org/flash-linear-attention.git@f0e213dbd8b5fb90c3c7eca869ac1706d5377139",
46
48
  # tilelang version-pinned in lockstep with Dockerfile.worker + perf.py runtime reinstall.
47
49
  "tilelang==0.1.11",
@@ -110,12 +112,13 @@ def _effective_worker_env(spec=None) -> dict[str, str]:
110
112
  # Chalk is published to PUBLIC PyPI on every version bump (chalk .github/workflows/publish.yml).
111
113
  # Pin the exact PUBLIC version so worker + kernel-cache-bake pods install with NO GitHub auth — the
112
114
  # chalk repo is INTERNAL, so a git+https default made installs fail wherever GITHUB_TOKEN is absent
113
- # (bake pod, tokenless workers). freesolo-chalk 0.5.0 = chalk PR #21 fafe167 (standalone, Liger fully
114
- # replaced, + GRPO op + LoRA grad-gate). Bump DEFAULT_CHALK_VERSION when the merged kernel surface moves.
115
- DEFAULT_CHALK_VERSION = "0.5.1"
115
+ # (bake pod, tokenless workers). freesolo-chalk 0.5.2 = chalk dev->main sync #44 (standalone, Liger
116
+ # fully replaced; adds arch-TUNED gdn_gated_rmsnorm + lora on sm89/sm90/sm100, MoE grouped-GEMM,
117
+ # serving surface, MiniCPM/Llama kernels). Bump DEFAULT_CHALK_VERSION when the merged kernel surface moves.
118
+ DEFAULT_CHALK_VERSION = "0.5.2"
116
119
  DEFAULT_CHALK_SPEC = f"freesolo-chalk=={DEFAULT_CHALK_VERSION}"
117
120
  # Provenance only (kernel-cache fingerprint / traceability): the chalk commit this version was cut from.
118
- LATEST_CHALK_MAIN_SHA = "fafe167158eb3b7c947e7182ea4eddc351e4ca7d"
121
+ LATEST_CHALK_MAIN_SHA = "37b2fb9e1a123ceb902ba6ffc4ed182182c6e7d7"
119
122
 
120
123
 
121
124
  def chalk_extra_pip(spec=None) -> list[str]:
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "freesolo-flash-dev"
3
- version = "0.2.41"
3
+ version = "0.2.43"
4
4
  description = "Flash — managed LoRA post-training (SFT/GRPO) 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).
@@ -106,7 +106,7 @@ artifacts = ["flash/py.typed"]
106
106
  # auto-published by .github/workflows/publish-dev.yml: a push to `dev` whose version isn't yet on
107
107
  # PyPI publishes it; pushes that don't change it find it already published and no-op. So cutting a
108
108
  # dev-channel release = bump this (and [project].version) and merge to `dev`.
109
- version = "0.2.41"
109
+ version = "0.2.43"
110
110
 
111
111
  [tool.pytest.ini_options]
112
112
  pythonpath = ["."]