soup-cli 0.71.2__tar.gz → 0.71.3__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 (774) hide show
  1. {soup_cli-0.71.2 → soup_cli-0.71.3}/CHANGELOG.md +35 -0
  2. {soup_cli-0.71.2 → soup_cli-0.71.3}/CONTRIBUTING.md +3 -1
  3. {soup_cli-0.71.2 → soup_cli-0.71.3}/PKG-INFO +19 -14
  4. {soup_cli-0.71.2 → soup_cli-0.71.3}/README.md +13 -13
  5. {soup_cli-0.71.2 → soup_cli-0.71.3}/docs/adapters-and-governance.md +36 -8
  6. {soup_cli-0.71.2 → soup_cli-0.71.3}/docs/commands.md +7 -1
  7. {soup_cli-0.71.2 → soup_cli-0.71.3}/pyproject.toml +7 -2
  8. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/__init__.py +1 -1
  9. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/cans/pack.py +4 -0
  10. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/cans/schema.py +49 -2
  11. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/cli.py +110 -3
  12. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/airgap.py +60 -0
  13. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/can.py +40 -1
  14. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/train.py +75 -10
  15. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/airgap_bundle.py +47 -1
  16. soup_cli-0.71.3/src/soup_cli/utils/annex_xi.py +458 -0
  17. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/energy.py +124 -3
  18. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/paths.py +32 -0
  19. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_cans.py +2 -2
  20. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_part_a_wave2.py +15 -4
  21. soup_cli-0.71.3/tests/test_v0713.py +1048 -0
  22. soup_cli-0.71.2/src/soup_cli/utils/annex_xi.py +0 -218
  23. {soup_cli-0.71.2 → soup_cli-0.71.3}/.dockerignore +0 -0
  24. {soup_cli-0.71.2 → soup_cli-0.71.3}/.github/FUNDING.yml +0 -0
  25. {soup_cli-0.71.2 → soup_cli-0.71.3}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  26. {soup_cli-0.71.2 → soup_cli-0.71.3}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  27. {soup_cli-0.71.2 → soup_cli-0.71.3}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  28. {soup_cli-0.71.2 → soup_cli-0.71.3}/.github/pull_request_template.md +0 -0
  29. {soup_cli-0.71.2 → soup_cli-0.71.3}/.github/workflows/ci.yml +0 -0
  30. {soup_cli-0.71.2 → soup_cli-0.71.3}/.github/workflows/docker.yml +0 -0
  31. {soup_cli-0.71.2 → soup_cli-0.71.3}/.github/workflows/publish.yml +0 -0
  32. {soup_cli-0.71.2 → soup_cli-0.71.3}/.github/workflows/recipe-validation.yml +0 -0
  33. {soup_cli-0.71.2 → soup_cli-0.71.3}/.gitignore +0 -0
  34. {soup_cli-0.71.2 → soup_cli-0.71.3}/.pre-commit-config.yaml +0 -0
  35. {soup_cli-0.71.2 → soup_cli-0.71.3}/AGENTS.md +0 -0
  36. {soup_cli-0.71.2 → soup_cli-0.71.3}/CODEOWNERS +0 -0
  37. {soup_cli-0.71.2 → soup_cli-0.71.3}/CODE_OF_CONDUCT.md +0 -0
  38. {soup_cli-0.71.2 → soup_cli-0.71.3}/Dockerfile +0 -0
  39. {soup_cli-0.71.2 → soup_cli-0.71.3}/LICENSE +0 -0
  40. {soup_cli-0.71.2 → soup_cli-0.71.3}/NOTICE +0 -0
  41. {soup_cli-0.71.2 → soup_cli-0.71.3}/SECURITY.md +0 -0
  42. {soup_cli-0.71.2 → soup_cli-0.71.3}/docker-compose.yml +0 -0
  43. {soup_cli-0.71.2 → soup_cli-0.71.3}/docs/README.md +0 -0
  44. {soup_cli-0.71.2 → soup_cli-0.71.3}/docs/backends-and-ops.md +0 -0
  45. {soup_cli-0.71.2 → soup_cli-0.71.3}/docs/data.md +0 -0
  46. {soup_cli-0.71.2 → soup_cli-0.71.3}/docs/evaluation.md +0 -0
  47. {soup_cli-0.71.2 → soup_cli-0.71.3}/docs/models.md +0 -0
  48. {soup_cli-0.71.2 → soup_cli-0.71.3}/docs/peft-and-efficiency.md +0 -0
  49. {soup_cli-0.71.2 → soup_cli-0.71.3}/docs/performance-and-quantization.md +0 -0
  50. {soup_cli-0.71.2 → soup_cli-0.71.3}/docs/serving-and-export.md +0 -0
  51. {soup_cli-0.71.2 → soup_cli-0.71.3}/docs/training.md +0 -0
  52. {soup_cli-0.71.2 → soup_cli-0.71.3}/examples/README.md +0 -0
  53. {soup_cli-0.71.2 → soup_cli-0.71.3}/examples/configs/dpo_chat.yaml +0 -0
  54. {soup_cli-0.71.2 → soup_cli-0.71.3}/examples/configs/dpo_example.yaml +0 -0
  55. {soup_cli-0.71.2 → soup_cli-0.71.3}/examples/configs/grpo_reasoning.yaml +0 -0
  56. {soup_cli-0.71.2 → soup_cli-0.71.3}/examples/configs/rlhf_step1_sft.yaml +0 -0
  57. {soup_cli-0.71.2 → soup_cli-0.71.3}/examples/configs/rlhf_step2_reward.yaml +0 -0
  58. {soup_cli-0.71.2 → soup_cli-0.71.3}/examples/configs/rlhf_step3_ppo.yaml +0 -0
  59. {soup_cli-0.71.2 → soup_cli-0.71.3}/examples/configs/sft_basic.yaml +0 -0
  60. {soup_cli-0.71.2 → soup_cli-0.71.3}/examples/configs/vision_llama.yaml +0 -0
  61. {soup_cli-0.71.2 → soup_cli-0.71.3}/examples/data/alpaca_tiny.jsonl +0 -0
  62. {soup_cli-0.71.2 → soup_cli-0.71.3}/examples/data/chat_preferences.jsonl +0 -0
  63. {soup_cli-0.71.2 → soup_cli-0.71.3}/examples/data/dpo_sample.jsonl +0 -0
  64. {soup_cli-0.71.2 → soup_cli-0.71.3}/examples/data/reasoning_math.jsonl +0 -0
  65. {soup_cli-0.71.2 → soup_cli-0.71.3}/examples/synthetic_workflow.md +0 -0
  66. {soup_cli-0.71.2 → soup_cli-0.71.3}/examples/synthetic_workflow.yaml +0 -0
  67. {soup_cli-0.71.2 → soup_cli-0.71.3}/soup.png +0 -0
  68. {soup_cli-0.71.2 → soup_cli-0.71.3}/soup_logo_svg.svg +0 -0
  69. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/__main__.py +0 -0
  70. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/autopilot/__init__.py +0 -0
  71. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/autopilot/analyzer.py +0 -0
  72. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/autopilot/decisions.py +0 -0
  73. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/autopilot/generate_config.py +0 -0
  74. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/cans/__init__.py +0 -0
  75. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/cans/publish.py +0 -0
  76. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/cans/run.py +0 -0
  77. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/cans/unpack.py +0 -0
  78. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/cans/verify.py +0 -0
  79. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/__init__.py +0 -0
  80. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/_eval_v0550.py +0 -0
  81. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/_eval_v0610.py +0 -0
  82. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/_eval_v0650.py +0 -0
  83. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/ab.py +0 -0
  84. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/active_sample.py +0 -0
  85. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/adapters.py +0 -0
  86. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/advise.py +0 -0
  87. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/agent.py +0 -0
  88. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/apple_adapter.py +0 -0
  89. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/attest.py +0 -0
  90. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/audit_log.py +0 -0
  91. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/autopilot.py +0 -0
  92. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/bench.py +0 -0
  93. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/bom.py +0 -0
  94. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/build.py +0 -0
  95. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/chat.py +0 -0
  96. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/compile_cmd.py +0 -0
  97. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/compile_tools.py +0 -0
  98. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/completions.py +0 -0
  99. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/cost.py +0 -0
  100. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/data.py +0 -0
  101. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/data_forge.py +0 -0
  102. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/data_mix.py +0 -0
  103. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/data_score.py +0 -0
  104. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/delinearize_llama4.py +0 -0
  105. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/deploy.py +0 -0
  106. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/diagnose.py +0 -0
  107. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/diff.py +0 -0
  108. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/distill_prompt.py +0 -0
  109. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/doctor.py +0 -0
  110. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/drift_alarm.py +0 -0
  111. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/edit.py +0 -0
  112. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/env.py +0 -0
  113. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/eval.py +0 -0
  114. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/expect.py +0 -0
  115. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/export.py +0 -0
  116. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/fetch.py +0 -0
  117. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/generate.py +0 -0
  118. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/history.py +0 -0
  119. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/infer.py +0 -0
  120. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/ingest.py +0 -0
  121. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/init.py +0 -0
  122. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/iterative_dpo.py +0 -0
  123. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/license_advisor.py +0 -0
  124. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/llama.py +0 -0
  125. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/local_rl.py +0 -0
  126. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/lock.py +0 -0
  127. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/loop.py +0 -0
  128. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/merge.py +0 -0
  129. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/merge_sharded_fsdp_weights.py +0 -0
  130. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/migrate.py +0 -0
  131. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/monitor.py +0 -0
  132. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/plan.py +0 -0
  133. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/plugins.py +0 -0
  134. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/probe.py +0 -0
  135. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/profile.py +0 -0
  136. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/prune_prompt.py +0 -0
  137. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/push.py +0 -0
  138. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/quantize.py +0 -0
  139. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/quickstart.py +0 -0
  140. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/recipes.py +0 -0
  141. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/registry.py +0 -0
  142. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/runs.py +0 -0
  143. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/serve.py +0 -0
  144. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/steer.py +0 -0
  145. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/sweep.py +0 -0
  146. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/tokenizer.py +0 -0
  147. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/tui.py +0 -0
  148. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/tunability.py +0 -0
  149. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/ui.py +0 -0
  150. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/commands/why.py +0 -0
  151. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/config/__init__.py +0 -0
  152. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/config/loader.py +0 -0
  153. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/config/schema.py +0 -0
  154. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/data/__init__.py +0 -0
  155. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/data/_fixtures/alpaca_tiny.jsonl +0 -0
  156. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/data/_fixtures/behavior/elephant.jsonl +0 -0
  157. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/data/_fixtures/behavior/harmbench.jsonl +0 -0
  158. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/data/_fixtures/behavior/jailbreakbench.jsonl +0 -0
  159. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/data/_fixtures/behavior/syceval.jsonl +0 -0
  160. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/data/_fixtures/behavior/xstest.jsonl +0 -0
  161. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/data/_fixtures/chat_preferences.jsonl +0 -0
  162. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/data/_fixtures/dpo_sample.jsonl +0 -0
  163. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/data/_fixtures/reasoning_math.jsonl +0 -0
  164. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/data/_fixtures/unlearning/muse_demo.jsonl +0 -0
  165. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/data/_fixtures/unlearning/tofu_demo.jsonl +0 -0
  166. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/data/_fixtures/unlearning/wmdp_demo.jsonl +0 -0
  167. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/data/augment.py +0 -0
  168. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/data/chat_templates.py +0 -0
  169. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/data/collators.py +0 -0
  170. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/data/formats.py +0 -0
  171. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/data/loader.py +0 -0
  172. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/data/loss_mask.py +0 -0
  173. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/data/providers/__init__.py +0 -0
  174. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/data/providers/_utils.py +0 -0
  175. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/data/providers/anthropic.py +0 -0
  176. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/data/providers/ollama.py +0 -0
  177. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/data/providers/vllm.py +0 -0
  178. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/data/sft_format.py +0 -0
  179. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/data/templates/__init__.py +0 -0
  180. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/data/templates/code.py +0 -0
  181. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/data/templates/conversation.py +0 -0
  182. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/data/templates/preference.py +0 -0
  183. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/data/templates/qa.py +0 -0
  184. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/data/templates/reasoning.py +0 -0
  185. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/data/templates/tool_calling.py +0 -0
  186. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/data/templates/verifiable.py +0 -0
  187. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/data/traces/__init__.py +0 -0
  188. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/data/traces/pair_builder.py +0 -0
  189. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/data/traces/parsers.py +0 -0
  190. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/data/traces/quality.py +0 -0
  191. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/data/validator.py +0 -0
  192. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/eval/__init__.py +0 -0
  193. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/eval/arena.py +0 -0
  194. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/eval/benchmarks_v0_43.py +0 -0
  195. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/eval/calibrate.py +0 -0
  196. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/eval/checkpoint_intelligence.py +0 -0
  197. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/eval/custom.py +0 -0
  198. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/eval/forgetting.py +0 -0
  199. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/eval/gate.py +0 -0
  200. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/eval/human.py +0 -0
  201. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/eval/judge.py +0 -0
  202. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/eval/leaderboard.py +0 -0
  203. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/eval/quant_check.py +0 -0
  204. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/experiment/__init__.py +0 -0
  205. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/experiment/tracker.py +0 -0
  206. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/migrate/__init__.py +0 -0
  207. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/migrate/axolotl.py +0 -0
  208. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/migrate/common.py +0 -0
  209. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/migrate/llamafactory.py +0 -0
  210. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/migrate/unsloth.py +0 -0
  211. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/monitoring/__init__.py +0 -0
  212. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/monitoring/callback.py +0 -0
  213. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/monitoring/curriculum_callback.py +0 -0
  214. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/monitoring/display.py +0 -0
  215. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/monitoring/grpo_stability_callback.py +0 -0
  216. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/monitoring/hf_push.py +0 -0
  217. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/monitoring/plugin_callback.py +0 -0
  218. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/monitoring/trace_logger.py +0 -0
  219. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/plugins/__init__.py +0 -0
  220. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/py.typed +0 -0
  221. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/recipes/__init__.py +0 -0
  222. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/recipes/catalog.py +0 -0
  223. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/registry/__init__.py +0 -0
  224. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/registry/attach.py +0 -0
  225. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/registry/diff.py +0 -0
  226. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/registry/hashing.py +0 -0
  227. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/registry/store.py +0 -0
  228. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/templates/__init__.py +0 -0
  229. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/templates/audio.yaml +0 -0
  230. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/templates/bco.yaml +0 -0
  231. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/templates/chat.yaml +0 -0
  232. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/templates/code.yaml +0 -0
  233. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/templates/embedding.yaml +0 -0
  234. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/templates/fetch_examples/llama-3.1-8b-lora.yaml +0 -0
  235. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/templates/fetch_examples/qwen2.5-7b-dpo.yaml +0 -0
  236. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/templates/fetch_examples/zero3-cpu-offload.json +0 -0
  237. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/templates/ipo.yaml +0 -0
  238. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/templates/kto.yaml +0 -0
  239. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/templates/longcontext.yaml +0 -0
  240. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/templates/manifest.json +0 -0
  241. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/templates/medical.yaml +0 -0
  242. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/templates/moe.yaml +0 -0
  243. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/templates/orpo.yaml +0 -0
  244. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/templates/pretrain.yaml +0 -0
  245. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/templates/reasoning.yaml +0 -0
  246. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/templates/rlhf.yaml +0 -0
  247. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/templates/simpo.yaml +0 -0
  248. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/templates/tool-calling.yaml +0 -0
  249. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/templates/vision.yaml +0 -0
  250. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/trainer/__init__.py +0 -0
  251. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/trainer/bco.py +0 -0
  252. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/trainer/classifier.py +0 -0
  253. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/trainer/distill.py +0 -0
  254. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/trainer/dpo.py +0 -0
  255. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/trainer/embedding.py +0 -0
  256. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/trainer/grpo.py +0 -0
  257. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/trainer/ipo.py +0 -0
  258. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/trainer/kto.py +0 -0
  259. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/trainer/mlx_dpo.py +0 -0
  260. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/trainer/mlx_grpo.py +0 -0
  261. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/trainer/mlx_routing.py +0 -0
  262. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/trainer/mlx_sft.py +0 -0
  263. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/trainer/orpo.py +0 -0
  264. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/trainer/ppo.py +0 -0
  265. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/trainer/preference.py +0 -0
  266. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/trainer/pretrain.py +0 -0
  267. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/trainer/prm.py +0 -0
  268. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/trainer/reward_model.py +0 -0
  269. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/trainer/rewards.py +0 -0
  270. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/trainer/sft.py +0 -0
  271. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/trainer/simpo.py +0 -0
  272. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/trainer/unlearn.py +0 -0
  273. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/tui_app.py +0 -0
  274. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/ui/__init__.py +0 -0
  275. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/ui/app.py +0 -0
  276. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/ui/plugins/__init__.py +0 -0
  277. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/ui/static/app.js +0 -0
  278. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/ui/static/index.html +0 -0
  279. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/ui/static/logo.png +0 -0
  280. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/ui/static/logo.svg +0 -0
  281. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/ui/static/style.css +0 -0
  282. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/__init__.py +0 -0
  283. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/_eval_text.py +0 -0
  284. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/ab_test.py +0 -0
  285. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/activation_offload.py +0 -0
  286. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/active_sampler.py +0 -0
  287. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/adapter_bisect.py +0 -0
  288. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/adapter_branch.py +0 -0
  289. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/adapter_diff.py +0 -0
  290. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/adapter_merge.py +0 -0
  291. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/adapter_pr.py +0 -0
  292. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/adapter_scan.py +0 -0
  293. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/adapter_sign.py +0 -0
  294. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/advanced_precision.py +0 -0
  295. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/advise.py +0 -0
  296. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/advise_history.py +0 -0
  297. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/agent_forge.py +0 -0
  298. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/agent_rollout.py +0 -0
  299. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/anthropic_messages.py +0 -0
  300. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/apple_adapter.py +0 -0
  301. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/attest.py +0 -0
  302. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/audit_log.py +0 -0
  303. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/auto_quant.py +0 -0
  304. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/backend_detect.py +0 -0
  305. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/batch_probe.py +0 -0
  306. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/behavior_battery.py +0 -0
  307. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/bitnet.py +0 -0
  308. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/blame.py +0 -0
  309. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/block_expansion.py +0 -0
  310. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/bom.py +0 -0
  311. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/brain_rot.py +0 -0
  312. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/brain_rot_lang.py +0 -0
  313. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/build_dag.py +0 -0
  314. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/canary_discovery.py +0 -0
  315. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/canary_router.py +0 -0
  316. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/capability_suite.py +0 -0
  317. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/checklist_dsl.py +0 -0
  318. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/checkpoint_trigger.py +0 -0
  319. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/citation_faithful.py +0 -0
  320. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/classifier.py +0 -0
  321. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/cmaes_merge.py +0 -0
  322. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/compile_tools.py +0 -0
  323. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/completions.py +0 -0
  324. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/constants.py +0 -0
  325. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/convergence.py +0 -0
  326. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/crash.py +0 -0
  327. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/cross_doc_attn.py +0 -0
  328. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/curriculum.py +0 -0
  329. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/curriculum_dynamic.py +0 -0
  330. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/cut_ce.py +0 -0
  331. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/data_forge.py +0 -0
  332. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/data_mix.py +0 -0
  333. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/data_pipeline.py +0 -0
  334. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/data_score.py +0 -0
  335. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/deepspeed.py +0 -0
  336. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/delinearize_llama4.py +0 -0
  337. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/demo_bundles.py +0 -0
  338. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/deploy_autopilot.py +0 -0
  339. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/deploy_measure.py +0 -0
  340. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/diagnose/__init__.py +0 -0
  341. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/diagnose/_common.py +0 -0
  342. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/diagnose/badge.py +0 -0
  343. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/diagnose/contamination.py +0 -0
  344. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/diagnose/forgetting.py +0 -0
  345. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/diagnose/format.py +0 -0
  346. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/diagnose/memorization.py +0 -0
  347. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/diagnose/mode_collapse.py +0 -0
  348. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/diagnose/refusal.py +0 -0
  349. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/diagnose/report.py +0 -0
  350. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/diagnose/runner.py +0 -0
  351. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/distill.py +0 -0
  352. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/dpo_variants.py +0 -0
  353. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/drift_alarm.py +0 -0
  354. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/ebft_gdpo.py +0 -0
  355. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/echo_trap.py +0 -0
  356. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/edit_diff.py +0 -0
  357. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/edit_governor.py +0 -0
  358. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/encoding.py +0 -0
  359. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/env_lock.py +0 -0
  360. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/errors.py +0 -0
  361. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/eval_design.py +0 -0
  362. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/eval_gate_hook.py +0 -0
  363. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/eval_lock_coverage.py +0 -0
  364. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/expectations.py +0 -0
  365. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/fetch_examples.py +0 -0
  366. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/flash_attn.py +0 -0
  367. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/fp8.py +0 -0
  368. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/freeze.py +0 -0
  369. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/fsdp.py +0 -0
  370. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/fsdp_consolidate.py +0 -0
  371. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/galore.py +0 -0
  372. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/gguf_quant.py +0 -0
  373. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/gpu.py +0 -0
  374. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/gpu_monitor.py +0 -0
  375. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/grace_codebook.py +0 -0
  376. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/graceful_save.py +0 -0
  377. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/grad_accum.py +0 -0
  378. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/gradient_ckpt.py +0 -0
  379. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/grpo_long_context.py +0 -0
  380. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/grpo_variants.py +0 -0
  381. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/hardware_fit.py +0 -0
  382. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/hf.py +0 -0
  383. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/hf_space.py +0 -0
  384. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/hubs.py +0 -0
  385. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/ingest_sources.py +0 -0
  386. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/integrations.py +0 -0
  387. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/interference.py +0 -0
  388. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/irt.py +0 -0
  389. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/iterative_dpo.py +0 -0
  390. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/jinja_analyzer.py +0 -0
  391. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/kernel_picker.py +0 -0
  392. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/knowledge_edit.py +0 -0
  393. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/kv_cache.py +0 -0
  394. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/launcher.py +0 -0
  395. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/license_advisor.py +0 -0
  396. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/license_matrix.py +0 -0
  397. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/liger.py +0 -0
  398. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/llama_proxy.py +0 -0
  399. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/llama_server_timings.py +0 -0
  400. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/local_rl.py +0 -0
  401. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/loftq_init.py +0 -0
  402. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/log_level.py +0 -0
  403. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/long_context.py +0 -0
  404. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/longlora.py +0 -0
  405. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/loop_budget.py +0 -0
  406. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/loop_daemon.py +0 -0
  407. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/loop_iteration.py +0 -0
  408. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/loop_state.py +0 -0
  409. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/lr_finder.py +0 -0
  410. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/lr_groups.py +0 -0
  411. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/magpie.py +0 -0
  412. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/metrics.py +0 -0
  413. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/mii.py +0 -0
  414. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/minillm.py +0 -0
  415. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/mix_proxy.py +0 -0
  416. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/mixed_precision.py +0 -0
  417. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/mlx.py +0 -0
  418. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/moe.py +0 -0
  419. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/moe_quant.py +0 -0
  420. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/mole_routing.py +0 -0
  421. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/multipack.py +0 -0
  422. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/multipack_sampler.py +0 -0
  423. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/multipack_trainer.py +0 -0
  424. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/namespace_pin.py +0 -0
  425. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/neat_packing.py +0 -0
  426. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/ngram_spec.py +0 -0
  427. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/nlg_metrics.py +0 -0
  428. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/ollama.py +0 -0
  429. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/onboarding.py +0 -0
  430. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/optimizer_zoo.py +0 -0
  431. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/peft_builder.py +0 -0
  432. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/peft_patches.py +0 -0
  433. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/peft_wiring.py +0 -0
  434. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/persona_hub.py +0 -0
  435. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/pipeline.py +0 -0
  436. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/preference_combine.py +0 -0
  437. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/prm.py +0 -0
  438. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/probe_pack.py +0 -0
  439. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/profiler.py +0 -0
  440. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/profiling.py +0 -0
  441. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/profiling_v0_43.py +0 -0
  442. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/prompt_compile.py +0 -0
  443. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/prompt_distill.py +0 -0
  444. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/prune_prompt.py +0 -0
  445. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/qat.py +0 -0
  446. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/qr_url.py +0 -0
  447. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/quality.py +0 -0
  448. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/quant_menu.py +0 -0
  449. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/ra_dit.py +0 -0
  450. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/reasoning_effort.py +0 -0
  451. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/reasoning_parser.py +0 -0
  452. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/recipe_dag.py +0 -0
  453. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/recipe_run.py +0 -0
  454. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/registry.py +0 -0
  455. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/relora.py +0 -0
  456. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/replay.py +0 -0
  457. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/repro_receipt.py +0 -0
  458. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/reward_hacking.py +0 -0
  459. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/ring_attention.py +0 -0
  460. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/rl_checkpoint.py +0 -0
  461. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/run_cost.py +0 -0
  462. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/sae_diff.py +0 -0
  463. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/save_formats.py +0 -0
  464. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/server_tools.py +0 -0
  465. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/sglang.py +0 -0
  466. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/shortcuts.py +0 -0
  467. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/signing.py +0 -0
  468. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/sleeper_probe.py +0 -0
  469. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/soup_lock.py +0 -0
  470. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/spec_pairing.py +0 -0
  471. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/spike_recovery.py +0 -0
  472. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/sse_train_stream.py +0 -0
  473. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/steering.py +0 -0
  474. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/strict_safetensors.py +0 -0
  475. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/structured_output.py +0 -0
  476. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/sweep_config.py +0 -0
  477. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/tail_latency.py +0 -0
  478. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/terraform_plan.py +0 -0
  479. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/tool_outputs.py +0 -0
  480. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/topology.py +0 -0
  481. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/tracing.py +0 -0
  482. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/trackers.py +0 -0
  483. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/train_event_buffer.py +0 -0
  484. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/trainer_plugins.py +0 -0
  485. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/trust_remote.py +0 -0
  486. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/tts.py +0 -0
  487. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/tunability.py +0 -0
  488. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/ui_env.py +0 -0
  489. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/uld.py +0 -0
  490. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/unlearning.py +0 -0
  491. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/unlearning_eval.py +0 -0
  492. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/unsloth.py +0 -0
  493. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/v028_features.py +0 -0
  494. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/vector_bank.py +0 -0
  495. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/vllm.py +0 -0
  496. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/vscode_setup.py +0 -0
  497. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/warmup.py +0 -0
  498. {soup_cli-0.71.2 → soup_cli-0.71.3}/src/soup_cli/utils/why.py +0 -0
  499. {soup_cli-0.71.2 → soup_cli-0.71.3}/templates/chat.yaml +0 -0
  500. {soup_cli-0.71.2 → soup_cli-0.71.3}/templates/code.yaml +0 -0
  501. {soup_cli-0.71.2 → soup_cli-0.71.3}/templates/medical.yaml +0 -0
  502. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/__init__.py +0 -0
  503. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/conftest.py +0 -0
  504. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/qa/v053_qa.md +0 -0
  505. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_adapters.py +0 -0
  506. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_advanced_peft.py +0 -0
  507. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_assistant_mask.py +0 -0
  508. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_audio.py +0 -0
  509. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_auto_tuning.py +0 -0
  510. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_autopilot.py +0 -0
  511. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_awq_gptq_export.py +0 -0
  512. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_batch_probe.py +0 -0
  513. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_bco.py +0 -0
  514. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_bench.py +0 -0
  515. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_brain_rot_multilingual.py +0 -0
  516. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_bugfixes.py +0 -0
  517. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_callback.py +0 -0
  518. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_chat.py +0 -0
  519. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_chat_template.py +0 -0
  520. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_cli.py +0 -0
  521. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_cli_subprocess.py +0 -0
  522. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_config.py +0 -0
  523. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_cost.py +0 -0
  524. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_crash_reporter.py +0 -0
  525. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_curriculum.py +0 -0
  526. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_data.py +0 -0
  527. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_data_augment.py +0 -0
  528. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_data_sample.py +0 -0
  529. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_data_split.py +0 -0
  530. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_data_tools.py +0 -0
  531. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_dataset_hub.py +0 -0
  532. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_dataset_registry.py +0 -0
  533. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_deepspeed.py +0 -0
  534. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_deploy_ollama.py +0 -0
  535. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_diff.py +0 -0
  536. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_display.py +0 -0
  537. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_doctor.py +0 -0
  538. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_dpo_example.py +0 -0
  539. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_dpo_variants.py +0 -0
  540. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_embedding.py +0 -0
  541. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_errors.py +0 -0
  542. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_eval.py +0 -0
  543. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_eval_gate.py +0 -0
  544. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_eval_platform.py +0 -0
  545. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_export.py +0 -0
  546. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_formats.py +0 -0
  547. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_fp8_recipe.py +0 -0
  548. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_freeze_training.py +0 -0
  549. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_generate.py +0 -0
  550. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_gpu.py +0 -0
  551. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_grpo.py +0 -0
  552. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_hf_integration.py +0 -0
  553. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_infer.py +0 -0
  554. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_inference_advanced.py +0 -0
  555. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_init.py +0 -0
  556. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_ipo.py +0 -0
  557. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_jinja_analyzer.py +0 -0
  558. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_kto.py +0 -0
  559. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_loader.py +0 -0
  560. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_log_level.py +0 -0
  561. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_loss_watchdog.py +0 -0
  562. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_merge.py +0 -0
  563. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_migrate.py +0 -0
  564. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_mlx_backend.py +0 -0
  565. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_moe.py +0 -0
  566. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_multi_adapter.py +0 -0
  567. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_multi_gpu.py +0 -0
  568. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_multipack_config.py +0 -0
  569. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_multipack_invariants.py +0 -0
  570. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_multipack_sampler.py +0 -0
  571. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_neat_packing.py +0 -0
  572. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_neftune_rslora.py +0 -0
  573. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_onnx_tensorrt_export.py +0 -0
  574. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_orpo.py +0 -0
  575. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_packing.py +0 -0
  576. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_part_a_wave1.py +0 -0
  577. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_part_b.py +0 -0
  578. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_part_c.py +0 -0
  579. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_part_d.py +0 -0
  580. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_part_e.py +0 -0
  581. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_part_f_hardening.py +0 -0
  582. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_peft_methods.py +0 -0
  583. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_peft_patches.py +0 -0
  584. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_performance.py +0 -0
  585. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_pissa_init.py +0 -0
  586. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_ppo.py +0 -0
  587. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_preference_dispatcher.py +0 -0
  588. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_preference_multi.py +0 -0
  589. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_preference_multi_runtime.py +0 -0
  590. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_pretrain.py +0 -0
  591. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_profile.py +0 -0
  592. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_profiling.py +0 -0
  593. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_progress.py +0 -0
  594. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_push.py +0 -0
  595. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_qat.py +0 -0
  596. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_quality_filter.py +0 -0
  597. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_quant_check.py +0 -0
  598. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_quant_menu.py +0 -0
  599. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_quickstart.py +0 -0
  600. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_rank_pattern.py +0 -0
  601. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_recipes.py +0 -0
  602. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_recipes_v031.py +0 -0
  603. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_refusal_multilingual.py +0 -0
  604. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_registry.py +0 -0
  605. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_relora.py +0 -0
  606. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_replay.py +0 -0
  607. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_resume.py +0 -0
  608. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_rlvr.py +0 -0
  609. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_run_cost.py +0 -0
  610. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_runs.py +0 -0
  611. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_serve.py +0 -0
  612. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_server_generate.py +0 -0
  613. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_sglang_serve.py +0 -0
  614. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_simpo.py +0 -0
  615. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_smoke_train.py +0 -0
  616. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_speculative_decoding.py +0 -0
  617. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_sweep.py +0 -0
  618. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_synth_data_pro.py +0 -0
  619. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_templates_yaml.py +0 -0
  620. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_tensorboard.py +0 -0
  621. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_tool_calling.py +0 -0
  622. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_trace_to_pref.py +0 -0
  623. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_tracker.py +0 -0
  624. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_trainer_coverage_v035.py +0 -0
  625. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_trainer_init.py +0 -0
  626. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_training_intelligence.py +0 -0
  627. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_training_speed.py +0 -0
  628. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_trust_remote_code.py +0 -0
  629. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_tui.py +0 -0
  630. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_ui.py +0 -0
  631. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_ui_chat.py +0 -0
  632. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_ui_config_builder.py +0 -0
  633. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_ui_live_monitor.py +0 -0
  634. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_ui_metrics.py +0 -0
  635. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_unsloth.py +0 -0
  636. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0401_part_c.py +0 -0
  637. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0401_part_d.py +0 -0
  638. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0401_part_e.py +0 -0
  639. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0402_part_a.py +0 -0
  640. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0402_part_b.py +0 -0
  641. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0403_part_a.py +0 -0
  642. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0403_part_b.py +0 -0
  643. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0403_part_c.py +0 -0
  644. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0404_part_a.py +0 -0
  645. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0404_part_b.py +0 -0
  646. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0405_part_a.py +0 -0
  647. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0406_part_a.py +0 -0
  648. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0410_part_a.py +0 -0
  649. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0410_part_b.py +0 -0
  650. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0410_part_c.py +0 -0
  651. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0420.py +0 -0
  652. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0430_part_a.py +0 -0
  653. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0430_part_b.py +0 -0
  654. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0430_part_c.py +0 -0
  655. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0430_part_d.py +0 -0
  656. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0440_part_a.py +0 -0
  657. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0440_part_b.py +0 -0
  658. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0440_part_c.py +0 -0
  659. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0440_part_d.py +0 -0
  660. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0440_review_followups.py +0 -0
  661. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0450.py +0 -0
  662. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0460_part_a.py +0 -0
  663. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0460_part_b.py +0 -0
  664. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0470_part_a.py +0 -0
  665. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0470_part_b.py +0 -0
  666. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0480_part_a.py +0 -0
  667. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0480_part_b.py +0 -0
  668. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0490.py +0 -0
  669. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0500_part_a.py +0 -0
  670. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0500_part_b.py +0 -0
  671. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0500_part_c.py +0 -0
  672. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0500_part_d.py +0 -0
  673. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0500_part_e.py +0 -0
  674. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0510.py +0 -0
  675. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0520.py +0 -0
  676. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0530.py +0 -0
  677. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v05310.py +0 -0
  678. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v05311.py +0 -0
  679. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0531_109.py +0 -0
  680. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0531_139.py +0 -0
  681. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0531_142.py +0 -0
  682. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0531_82.py +0 -0
  683. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0532.py +0 -0
  684. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0533.py +0 -0
  685. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0534.py +0 -0
  686. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0535.py +0 -0
  687. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0536.py +0 -0
  688. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0537.py +0 -0
  689. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0538.py +0 -0
  690. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0539.py +0 -0
  691. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0540.py +0 -0
  692. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0550.py +0 -0
  693. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0550_followups.py +0 -0
  694. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0560.py +0 -0
  695. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0570_part_a.py +0 -0
  696. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0570_part_b.py +0 -0
  697. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0570_part_c.py +0 -0
  698. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0570_part_d.py +0 -0
  699. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0580.py +0 -0
  700. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0590.py +0 -0
  701. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0600_part_a.py +0 -0
  702. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0600_part_b.py +0 -0
  703. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0600_part_c.py +0 -0
  704. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0600_part_d.py +0 -0
  705. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0600_part_e.py +0 -0
  706. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0600_part_f.py +0 -0
  707. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0610_part_a.py +0 -0
  708. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0610_part_b.py +0 -0
  709. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0610_part_c.py +0 -0
  710. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0610_part_d.py +0 -0
  711. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0610_part_e.py +0 -0
  712. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0620_followups.py +0 -0
  713. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0620_part_a.py +0 -0
  714. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0620_part_b.py +0 -0
  715. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0620_part_c.py +0 -0
  716. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0620_part_d.py +0 -0
  717. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0620_part_e.py +0 -0
  718. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0630_followups.py +0 -0
  719. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0630_part_a.py +0 -0
  720. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0630_part_b.py +0 -0
  721. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0630_part_c.py +0 -0
  722. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0630_part_d.py +0 -0
  723. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0630_part_e.py +0 -0
  724. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0631_206.py +0 -0
  725. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0640_followups.py +0 -0
  726. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0640_part_a.py +0 -0
  727. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0640_part_b.py +0 -0
  728. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0640_part_c.py +0 -0
  729. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0640_part_d.py +0 -0
  730. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0640_part_e.py +0 -0
  731. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0640_part_f.py +0 -0
  732. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0650_followups.py +0 -0
  733. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0650_part_a.py +0 -0
  734. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0650_part_b.py +0 -0
  735. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0650_part_c.py +0 -0
  736. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0650_part_d.py +0 -0
  737. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0650_part_e.py +0 -0
  738. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0660_cli.py +0 -0
  739. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0660_followups.py +0 -0
  740. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0660_part_a.py +0 -0
  741. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0660_part_b.py +0 -0
  742. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0660_part_c.py +0 -0
  743. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0660_part_d.py +0 -0
  744. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0660_part_e.py +0 -0
  745. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0670_followups.py +0 -0
  746. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0670_part_a.py +0 -0
  747. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0670_part_b.py +0 -0
  748. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0670_part_c.py +0 -0
  749. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0670_part_d.py +0 -0
  750. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0670_part_e.py +0 -0
  751. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0670_part_f.py +0 -0
  752. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0680_followups.py +0 -0
  753. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0680_part_a.py +0 -0
  754. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0680_part_b.py +0 -0
  755. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0680_part_c.py +0 -0
  756. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0680_part_d.py +0 -0
  757. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0680_part_e.py +0 -0
  758. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0690_part_a.py +0 -0
  759. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0690_part_b.py +0 -0
  760. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0690_part_c.py +0 -0
  761. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0690_part_d.py +0 -0
  762. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0690_part_e.py +0 -0
  763. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0700_part_a.py +0 -0
  764. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0700_part_b.py +0 -0
  765. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0700_part_c.py +0 -0
  766. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0700_part_d.py +0 -0
  767. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0700_part_e.py +0 -0
  768. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0700_part_f.py +0 -0
  769. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_v0712.py +0 -0
  770. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_validator.py +0 -0
  771. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_vision.py +0 -0
  772. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_vllm_serve.py +0 -0
  773. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_why.py +0 -0
  774. {soup_cli-0.71.2 → soup_cli-0.71.3}/tests/test_windows_encoding.py +0 -0
@@ -12,6 +12,41 @@ reproducing 70+ versions of notes.
12
12
 
13
13
  ## [Unreleased]
14
14
 
15
+ ## [0.71.3] - 2026-06-01
16
+
17
+ ### Added
18
+ - **Energy & CO2 measurement for training** — `soup train --track-energy` wraps
19
+ the training window in a codecarbon **offline** tracker (no IP-geolocation
20
+ network call) and reports kWh / CO2 / grid intensity, feeding those numbers
21
+ into `--annex-xi`. New `EnergyTracker` context manager; graceful no-op when
22
+ codecarbon is absent (`pip install soup-cli[carbon]`). `--energy-country`
23
+ picks the ISO-3166 alpha-3 grid for the CO2 estimate (default `USA`).
24
+ - **PDF Annex XI/XII documents** — `soup train --annex-xi report.pdf` now renders
25
+ a reportlab PDF (a `.md` path still renders markdown). `pip install
26
+ soup-cli[pdf]`.
27
+ - **Auto-populated training-corpus domains in Annex XI/XII** — the top crawled
28
+ domains (with shares) are now extracted from the training JSONL and listed in
29
+ the EU AI Act docs, replacing the previous empty placeholder.
30
+ - **Soup Can manifest v3 with embedded attestations** — `soup can pack --attest
31
+ <statement.json>` (repeatable) embeds in-toto Statements into a v3 can
32
+ manifest; v1/v2 cans still load. Each statement is shape- and size-validated.
33
+ - **Local audit log auto-instrumentation** — every `soup` command now appends one
34
+ HIPAA/SOC2-shaped record to `~/.soup/audit.jsonl` (secrets redacted, args
35
+ capped). Opt out per-invocation with `--no-audit-log` or globally with
36
+ `SOUP_NO_AUDIT_LOG=1`. Tail/rotate with `soup audit-log`.
37
+ - **Reproducibility receipt in airgap bundles** — `soup airgap-bundle
38
+ --repro-receipt <receipt.json>` embeds an SR 11-7 receipt as
39
+ `repro-receipt.json`; auto-detected from `<model>/repro-receipt.json` when not
40
+ supplied.
41
+
42
+ ### Security
43
+ - `soup can pack --attest` now rejects oversize attestation files by their raw
44
+ size *before* parsing them into memory (defence against memory-exhaustion).
45
+ - The new file-loading paths (attestation JSON, airgap receipt, training-corpus
46
+ scan, PDF write) are all cwd-contained + TOCTOU symlink-rejected and
47
+ size-capped; the audit auto-log redacts `hf_`/`sk-`/`Bearer` tokens and never
48
+ crashes the CLI on a broken log.
49
+
15
50
  ## [0.71.2] - 2026-06-01
16
51
 
17
52
  ### Added
@@ -33,6 +33,8 @@ This installs:
33
33
  pulled in too (since v0.71.0 these are an opt-in extra, not core deps)
34
34
  - `cryptography` — `[dev]` also pulls it in (it's the `[sign]` extra) so the
35
35
  ed25519 signing tests (`soup adapters sign` / `soup attest`) run in CI
36
+ - `reportlab` — `[dev]` also pulls it in (it's the `[pdf]` extra) so the
37
+ Annex XI/XII PDF tests (`soup train --annex-xi *.pdf`) run in CI
36
38
 
37
39
  ### 3. Verify Setup
38
40
 
@@ -118,7 +120,7 @@ src/soup_cli/
118
120
  templates/ - 17 built-in soup.yaml templates (YAML + manifest.json) with load_template loader (v0.39.0, +bco v0.40.0)
119
121
  ui/ - Web UI (FastAPI + HTML/JS SPA)
120
122
 
121
- tests/ - Test suite (272 files, 12259 tests)
123
+ tests/ - Test suite (273 files, 12342 tests)
122
124
  examples/ - Real-world config examples and datasets
123
125
  ```
124
126
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: soup-cli
3
- Version: 0.71.2
3
+ Version: 0.71.3
4
4
  Summary: Fine-tune LLMs in one command. No SSH, no config hell.
5
5
  Project-URL: Homepage, https://github.com/MakazhanAlpamys/Soup
6
6
  Project-URL: Repository, https://github.com/MakazhanAlpamys/Soup
@@ -39,6 +39,8 @@ Requires-Dist: librosa>=0.10.0; extra == 'audio'
39
39
  Requires-Dist: soundfile>=0.12.0; extra == 'audio'
40
40
  Provides-Extra: awq
41
41
  Requires-Dist: autoawq>=0.2.0; extra == 'awq'
42
+ Provides-Extra: carbon
43
+ Requires-Dist: codecarbon>=2.0.0; extra == 'carbon'
42
44
  Provides-Extra: cce
43
45
  Requires-Dist: cut-cross-entropy>=24.10.0; extra == 'cce'
44
46
  Provides-Extra: data
@@ -59,6 +61,7 @@ Requires-Dist: peft>=0.7.0; extra == 'dev'
59
61
  Requires-Dist: pre-commit>=3.5.0; extra == 'dev'
60
62
  Requires-Dist: pytest-cov>=4.0; extra == 'dev'
61
63
  Requires-Dist: pytest>=7.0; extra == 'dev'
64
+ Requires-Dist: reportlab>=4.0.0; extra == 'dev'
62
65
  Requires-Dist: ruff>=0.1.0; extra == 'dev'
63
66
  Requires-Dist: torch>=2.0.0; extra == 'dev'
64
67
  Requires-Dist: transformers<5.0.0,>=4.36.0; extra == 'dev'
@@ -80,6 +83,8 @@ Requires-Dist: mlx-lm>=0.20.0; extra == 'mlx'
80
83
  Requires-Dist: mlx>=0.20.0; extra == 'mlx'
81
84
  Provides-Extra: onnx
82
85
  Requires-Dist: optimum[onnxruntime]>=1.16.0; extra == 'onnx'
86
+ Provides-Extra: pdf
87
+ Requires-Dist: reportlab>=4.0.0; extra == 'pdf'
83
88
  Provides-Extra: qat
84
89
  Requires-Dist: torchao>=0.4.0; extra == 'qat'
85
90
  Provides-Extra: remote
@@ -178,19 +183,19 @@ infrastructure instead of improving models. Soup fixes that.
178
183
 
179
184
  ## What's New
180
185
 
181
- **v0.71.2Governance & supply-chain live.** Real signatures and supply-chain gates:
182
-
183
- - **ed25519 signing** — `soup adapters sign --backend ed25519 --key priv.pem` (or `--generate-key`)
184
- produces a real detached signature over the adapter's Merkle root; `soup adapters verify
185
- --public-key trusted.pem` does cryptographic authentication. Same for `soup attest emit
186
- --sign ed25519` + the new `soup attest verify`. Install with `pip install soup-cli[sign]`.
187
- - **Anti-AI-Jacking namespace pin** Hub model downloads now refuse a repo whose author silently
188
- changed (or whose creation date jumped backward), the classic namespace-re-creation attack.
189
- - **License-conflict gate at merge** — `soup adapters merge` auto-detects each adapter's license
190
- (from `adapter_config.json` / model card) and refuses incompatible combinations unless you pass
191
- `--license-override <reason>` (logged to the audit trail).
192
- - **Backdoor-scan gate at merge** refuses to merge any adapter that `soup adapters scan` flags
193
- FAIL unless you pass `--allow-unscanned`.
186
+ **v0.71.3Compliance / annex / audit / energy.** The EU AI Act + carbon + audit surfaces go live:
187
+
188
+ - **Energy & CO2 measurement** — `soup train --track-energy` measures the training window with an
189
+ offline carbon tracker (no network) and reports kWh / CO2, feeding them into the Annex doc.
190
+ Install with `pip install soup-cli[carbon]`.
191
+ - **PDF compliance docs** `soup train --annex-xi report.pdf` now renders a real PDF of the
192
+ EU AI Act Annex XI/XII (a `.md` path still gives markdown). The top crawled domains of your
193
+ training corpus are auto-listed. `pip install soup-cli[pdf]`.
194
+ - **Per-command audit log** — every `soup` command appends one HIPAA/SOC2 record to
195
+ `~/.soup/audit.jsonl` (secrets redacted). Opt out with `--no-audit-log` or `SOUP_NO_AUDIT_LOG=1`.
196
+ - **Signed Soup Cans + airgap receipts** — `soup can pack --attest statement.json` embeds in-toto
197
+ attestations into a can; `soup airgap-bundle --repro-receipt receipt.json` ships a reproducibility
198
+ receipt inside the offline bundle.
194
199
 
195
200
  Full history: [CHANGELOG.md](CHANGELOG.md) &middot; [GitHub Releases](https://github.com/MakazhanAlpamys/Soup/releases).
196
201
 
@@ -49,19 +49,19 @@ infrastructure instead of improving models. Soup fixes that.
49
49
 
50
50
  ## What's New
51
51
 
52
- **v0.71.2Governance & supply-chain live.** Real signatures and supply-chain gates:
53
-
54
- - **ed25519 signing** — `soup adapters sign --backend ed25519 --key priv.pem` (or `--generate-key`)
55
- produces a real detached signature over the adapter's Merkle root; `soup adapters verify
56
- --public-key trusted.pem` does cryptographic authentication. Same for `soup attest emit
57
- --sign ed25519` + the new `soup attest verify`. Install with `pip install soup-cli[sign]`.
58
- - **Anti-AI-Jacking namespace pin** Hub model downloads now refuse a repo whose author silently
59
- changed (or whose creation date jumped backward), the classic namespace-re-creation attack.
60
- - **License-conflict gate at merge** — `soup adapters merge` auto-detects each adapter's license
61
- (from `adapter_config.json` / model card) and refuses incompatible combinations unless you pass
62
- `--license-override <reason>` (logged to the audit trail).
63
- - **Backdoor-scan gate at merge** refuses to merge any adapter that `soup adapters scan` flags
64
- FAIL unless you pass `--allow-unscanned`.
52
+ **v0.71.3Compliance / annex / audit / energy.** The EU AI Act + carbon + audit surfaces go live:
53
+
54
+ - **Energy & CO2 measurement** — `soup train --track-energy` measures the training window with an
55
+ offline carbon tracker (no network) and reports kWh / CO2, feeding them into the Annex doc.
56
+ Install with `pip install soup-cli[carbon]`.
57
+ - **PDF compliance docs** `soup train --annex-xi report.pdf` now renders a real PDF of the
58
+ EU AI Act Annex XI/XII (a `.md` path still gives markdown). The top crawled domains of your
59
+ training corpus are auto-listed. `pip install soup-cli[pdf]`.
60
+ - **Per-command audit log** — every `soup` command appends one HIPAA/SOC2 record to
61
+ `~/.soup/audit.jsonl` (secrets redacted). Opt out with `--no-audit-log` or `SOUP_NO_AUDIT_LOG=1`.
62
+ - **Signed Soup Cans + airgap receipts** — `soup can pack --attest statement.json` embeds in-toto
63
+ attestations into a can; `soup airgap-bundle --repro-receipt receipt.json` ships a reproducibility
64
+ receipt inside the offline bundle.
65
65
 
66
66
  Full history: [CHANGELOG.md](CHANGELOG.md) &middot; [GitHub Releases](https://github.com/MakazhanAlpamys/Soup/releases).
67
67
 
@@ -275,6 +275,9 @@ Share a reproducible recipe as a single `.can` file — a tarball of the manifes
275
275
  # Pack a registry entry into a .can
276
276
  soup can pack --entry-id llama31-chat-v1 --out ./llama31-chat.can
277
277
 
278
+ # Embed in-toto attestations into the manifest (v3 cans; repeatable)
279
+ soup can pack --entry-id llama31-chat-v1 --out ./signed.can --attest att.json
280
+
278
281
  # Preview the manifest without extracting
279
282
  soup can inspect ./llama31-chat.can
280
283
 
@@ -358,29 +361,45 @@ Render an EU AI Act Annex XI (technical documentation, Sections 1+2) or Annex XI
358
361
  (Article 53(1)(d) public training summary) directly from a training run:
359
362
 
360
363
  ```bash
361
- soup train --config soup.yaml --annex-xi annex.md
364
+ soup train --config soup.yaml --annex-xi annex.md # markdown
365
+ soup train --config soup.yaml --annex-xi annex.pdf # PDF (pip install soup-cli[pdf])
366
+ soup train --config soup.yaml --track-energy --annex-xi annex.md # + measured kWh/CO2
362
367
  ```
363
368
 
364
369
  Top-10 domains by share, modality breakdown, training compute / kWh / CO₂, model
365
- description, base model, run id. Markdown body now; PDF in v0.59.1. Operator-controlled
366
- fields are escape-neutralised (`|[](){}!<>` + newline / CR / tab) so a malicious model
367
- name can't inject a forged heading into downstream PDF/HTML renderers.
370
+ description, base model, run id. A `.pdf` output path renders a reportlab PDF (a `.md`
371
+ path renders markdown). The **top crawled domains** are auto-extracted from the training
372
+ JSONL (`cfg.data.train`). With `--track-energy`, the measured energy is recorded in the
373
+ doc. Operator-controlled fields are escape-neutralised (`|[](){}!<>` + newline / CR / tab)
374
+ so a malicious model name can't inject a forged heading into downstream renderers.
375
+
376
+ ### Energy & CO₂ measurement (`--track-energy`)
377
+
378
+ `soup train --track-energy` wraps the training window in a codecarbon **offline** tracker
379
+ (no IP-geolocation network call). It reports kWh / CO₂ / grid intensity and feeds them into
380
+ `--annex-xi`. `--energy-country <ISO3>` picks the grid for the CO₂ estimate (default `USA`;
381
+ the kWh figure itself is country-independent). Requires `pip install soup-cli[carbon]`;
382
+ without it, `--track-energy` is a graceful no-op.
368
383
 
369
384
 
370
385
  ## Audit Log (`soup audit-log`)
371
386
 
372
- Tail or rotate the HIPAA/SOC2-shaped JSONL audit log at `~/.soup/audit.jsonl` (override
373
- via `SOUP_AUDIT_LOG_PATH`, containment-checked to `$HOME / $CWD / $TMPDIR`):
387
+ **Every `soup` command** now appends one HIPAA/SOC2-shaped record to the JSONL audit log at
388
+ `~/.soup/audit.jsonl` (override via `SOUP_AUDIT_LOG_PATH`, containment-checked to
389
+ `$HOME / $CWD / $TMPDIR`). Opt out per-invocation with `soup --no-audit-log <cmd>` or
390
+ globally with `SOUP_NO_AUDIT_LOG=1`. Tail or rotate:
374
391
 
375
392
  ```bash
376
393
  soup audit-log tail --limit 50 # Rich table view
377
394
  soup audit-log tail --json # raw JSONL for SIEM ingestion
378
395
  soup audit-log rotate --cap-mb 100 # force a rotation pass
396
+ soup --no-audit-log version # skip the audit line for this command
379
397
  ```
380
398
 
381
399
  PII redaction across **every** string field (`hf_*` / `sk-*` / `Bearer …` → `<redacted>`)
382
400
  via the v0.40.3 `_SECRET_RE` policy. POSIX `O_NOFOLLOW` + `0o600` perms, atomic-append,
383
- rotation at 100 MiB with symlink rejection at the backup path.
401
+ rotation at 100 MiB with symlink rejection at the backup path. The auto-instrumentation is
402
+ best-effort — a broken audit log never crashes the CLI.
384
403
 
385
404
 
386
405
  ## Reproducibility Receipt (`soup train --repro-receipt`)
@@ -490,7 +509,16 @@ merge with exit 3 unless you pass `--allow-unscanned`.
490
509
 
491
510
  Single signed tarball with model + datasets + wheels + CUDA kernels +
492
511
  embedded `manifest.json` listing SHA-256 per file. Sized for one-way
493
- physical-media transfer through a data diode. Default 100 GiB cap;
512
+ physical-media transfer through a data diode. A reproducibility receipt is
513
+ embedded as a top-level `repro-receipt.json` when you pass
514
+ `--repro-receipt <receipt.json>` (or auto-detected from
515
+ `<model>/repro-receipt.json`):
516
+
517
+ ```bash
518
+ soup airgap-bundle --model ./out --output bundle.tar --repro-receipt repro.json
519
+ ```
520
+
521
+ Default 100 GiB cap;
494
522
  refuses oversize. Deterministic dataset labeling by sorted basename
495
523
  (NOT argv order) so the same inputs in different argv order produce
496
524
  identical manifests. TOCTOU defence: `os.lstat + S_ISLNK` re-check on
@@ -157,7 +157,13 @@ soup adapters check-safetensors <adapter> [--strict] Refuse pickle / PyTorch-cl
157
157
  soup adapters merge ... [--license <id>] [--license-override <reason>] [--allow-unscanned] License + backdoor-scan gates (auto-detect license; scan FAIL refused)
158
158
  soup attest emit ... [--sign ed25519 --key <pem>] [-o att.json] in-toto/SLSA-3 attestation (+ .sig sidecar)
159
159
  soup attest verify <statement> --signature <sig> [--public-key <pem>] Verify ed25519 attestation signature
160
- soup airgap-bundle --model <m> --output <out.tar> Signed tarball for data-diode transfer
160
+ soup airgap-bundle --model <m> --output <out.tar> [--repro-receipt <r.json>] Signed tarball for data-diode transfer (embeds repro-receipt)
161
+ soup train --config soup.yaml --annex-xi <out.md|out.pdf> EU AI Act Annex XI/XII doc (markdown or PDF; top_domains auto-filled)
162
+ soup train --config soup.yaml --track-energy [--energy-country USA] codecarbon offline kWh/CO2 → annex-xi (pip install soup-cli[carbon])
163
+ soup train --config soup.yaml --repro-receipt <out.json> SR 11-7 reproducibility receipt
164
+ soup can pack --entry-id <id> --out r.can --attest <statement.json> Embed in-toto Statements into a v3 can manifest
165
+ soup audit-log tail / rotate Tail / rotate the per-command HIPAA/SOC2 audit log (~/.soup/audit.jsonl)
166
+ soup --no-audit-log <cmd> / SOUP_NO_AUDIT_LOG=1 Opt out of the per-command audit line
161
167
  soup eval unlearning <run-id> --benchmark tofu|muse|wmdp Forget Quality + Model Utility + PrivLeak verdict
162
168
  soup edit set --base <m> --method rome|memit|alphaedit --subject "..." --target "..." Surgical knowledge edit (--plan-only available)
163
169
  soup edit diff <before-run> <after-run> --probes p.jsonl Knowledge-injection diff visualizer
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "soup-cli"
7
- version = "0.71.2"
7
+ version = "0.71.3"
8
8
  description = "Fine-tune LLMs in one command. No SSH, no config hell."
9
9
  readme = "README.md"
10
10
  license = "Apache-2.0"
@@ -54,7 +54,7 @@ wandb = ["wandb>=0.15.0,<0.18.0"]
54
54
  # Self-references `[train]` so CI / contributors get the full training stack
55
55
  # (CI runs `pip install -e ".[dev]"`; without this every test would fail at
56
56
  # `import torch`).
57
- dev = ["soup-cli[train]", "cryptography>=41.0.0", "pytest>=7.0", "ruff>=0.1.0", "pytest-cov>=4.0", "httpx>=0.24.0", "mypy>=1.8.0", "pre-commit>=3.5.0"]
57
+ dev = ["soup-cli[train]", "cryptography>=41.0.0", "reportlab>=4.0.0", "pytest>=7.0", "ruff>=0.1.0", "pytest-cov>=4.0", "httpx>=0.24.0", "mypy>=1.8.0", "pre-commit>=3.5.0"]
58
58
  ui = ["fastapi>=0.104.0", "uvicorn>=0.24.0"]
59
59
  serve = ["fastapi>=0.104.0", "uvicorn>=0.24.0"]
60
60
  serve-fast = ["vllm>=0.4.0", "fastapi>=0.104.0", "uvicorn>=0.24.0"]
@@ -89,6 +89,11 @@ data-pro = ["langdetect>=1.0.9", "presidio-analyzer>=2.2.0"]
89
89
  # adapters sign`. Pure-offline; Sigstore keyless (OIDC + Fulcio/Rekor network)
90
90
  # stays infra-blocked and is NOT bundled here.
91
91
  sign = ["cryptography>=41.0.0"]
92
+ # v0.71.3 #181 — reportlab PDF rendering for `soup train --annex-xi *.pdf`.
93
+ pdf = ["reportlab>=4.0.0"]
94
+ # v0.71.3 #180 — codecarbon offline energy/CO2 measurement for
95
+ # `soup train --track-energy` (offline; no IP-geolocation network call).
96
+ carbon = ["codecarbon>=2.0.0"]
92
97
 
93
98
  [project.scripts]
94
99
  soup = "soup_cli.cli:run"
@@ -1,3 +1,3 @@
1
1
  """Soup CLI — Fine-tune LLMs in one command."""
2
2
 
3
- __version__ = "0.71.2"
3
+ __version__ = "0.71.3"
@@ -29,6 +29,7 @@ def _add_text(tar: tarfile.TarFile, name: str, content: str) -> None:
29
29
  def pack_entry(
30
30
  *, entry_id: str, out_path: str, author: str = "unknown",
31
31
  description: Optional[str] = None,
32
+ attestations: Optional[list[dict]] = None,
32
33
  ) -> Path:
33
34
  """Pack a registry entry as a ``.can`` tarball.
34
35
 
@@ -38,6 +39,8 @@ def pack_entry(
38
39
  at call time.
39
40
  author: author handle baked into the manifest.
40
41
  description: optional free-form description.
42
+ attestations: optional list of embedded in-toto Statements (v0.71.3
43
+ #182). Each is shape-validated by the manifest schema.
41
44
 
42
45
  Returns:
43
46
  The absolute path to the written file.
@@ -66,6 +69,7 @@ def pack_entry(
66
69
  base_hash=entry.get("entry_hash", ""),
67
70
  description=description or entry.get("notes"),
68
71
  tags=list(entry.get("tags", [])),
72
+ attestations=list(attestations or []),
69
73
  )
70
74
 
71
75
  out.parent.mkdir(parents=True, exist_ok=True)
@@ -2,18 +2,48 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import json
5
6
  import re
6
7
  from typing import Literal, Optional
7
8
 
8
9
  from pydantic import BaseModel, Field, field_validator
9
10
 
10
- CAN_FORMAT_VERSION = 2 # v0.33.0: deploy_targets + env capture (additive over v1)
11
- SUPPORTED_CAN_FORMAT_VERSIONS = (1, 2)
11
+ CAN_FORMAT_VERSION = 3 # v0.71.3 #182: attestations field (additive over v2)
12
+ SUPPORTED_CAN_FORMAT_VERSIONS = (1, 2, 3)
12
13
 
13
14
  _NAME_RE = re.compile(r"^[A-Za-z0-9][A-Za-z0-9_\-.]{0,127}$")
14
15
  _HF_NAME_RE = re.compile(r"^[A-Za-z0-9][A-Za-z0-9_\-./]{0,127}$")
15
16
  _HF_REPO_RE = re.compile(r"^[A-Za-z0-9][A-Za-z0-9_\-.]{0,95}/[A-Za-z0-9][A-Za-z0-9_\-.]{0,95}$")
16
17
 
18
+ # v0.71.3 #182 — caps on embedded in-toto attestations.
19
+ _MAX_ATTESTATIONS = 64
20
+ _MAX_ATTESTATION_BYTES = 1024 * 1024 # 1 MiB per statement
21
+
22
+
23
+ def validate_attestation_statement(stmt: object) -> dict:
24
+ """Validate one embedded in-toto Statement dict (v0.71.3 #182).
25
+
26
+ Shape-only: must be a dict carrying ``_type`` (str) and ``predicateType``
27
+ (str), and serialise to <= 1 MiB. Returns the statement unchanged.
28
+ """
29
+ if not isinstance(stmt, dict):
30
+ raise ValueError("attestation must be a dict (in-toto Statement)")
31
+ type_field = stmt.get("_type")
32
+ predicate_type = stmt.get("predicateType")
33
+ if not isinstance(type_field, str) or not type_field:
34
+ raise ValueError("attestation missing a non-empty '_type' string")
35
+ if not isinstance(predicate_type, str) or not predicate_type:
36
+ raise ValueError("attestation missing a non-empty 'predicateType' string")
37
+ try:
38
+ size = len(json.dumps(stmt).encode("utf-8"))
39
+ except (TypeError, ValueError) as exc:
40
+ raise ValueError(f"attestation is not JSON-serialisable: {exc}") from exc
41
+ if size > _MAX_ATTESTATION_BYTES:
42
+ raise ValueError(
43
+ f"attestation too large ({size} > {_MAX_ATTESTATION_BYTES} bytes)"
44
+ )
45
+ return stmt
46
+
17
47
 
18
48
  class DeployTarget(BaseModel):
19
49
  """One declarative deploy target embedded in a can manifest (v2+).
@@ -116,6 +146,23 @@ class Manifest(BaseModel):
116
146
  default_factory=list,
117
147
  description="Optional declarative deploy targets (v2+)",
118
148
  )
149
+ attestations: list[dict] = Field(
150
+ default_factory=list,
151
+ description="Optional embedded in-toto Statements (v3+)",
152
+ )
153
+
154
+ @field_validator("attestations", mode="before")
155
+ @classmethod
156
+ def _valid_attestations(cls, value: object) -> list[dict]:
157
+ if value is None:
158
+ return []
159
+ if not isinstance(value, list):
160
+ raise ValueError("attestations must be a list of in-toto Statements")
161
+ if len(value) > _MAX_ATTESTATIONS:
162
+ raise ValueError(
163
+ f"too many attestations ({len(value)} > {_MAX_ATTESTATIONS})"
164
+ )
165
+ return [validate_attestation_statement(s) for s in value]
119
166
 
120
167
  @field_validator("can_format_version")
121
168
  @classmethod
@@ -1,5 +1,6 @@
1
1
  """Main CLI entry point — all commands registered here."""
2
2
 
3
+ import os
3
4
  import sys
4
5
 
5
6
  # UTF-8 stdio bootstrap (v0.40.1 Part A) — must run before any Rich console
@@ -71,6 +72,12 @@ console = Console()
71
72
  _verbose = False
72
73
  # Global log level (resolved string), set by main() callback
73
74
  _log_level = "normal"
75
+ # v0.71.3 #183 — audit-log opt-out, set by the --no-audit-log callback flag.
76
+ _audit_disabled = False
77
+
78
+ # Global options that consume a following value (so the audit command-splitter
79
+ # does not mistake the value for the subcommand name).
80
+ _GLOBAL_VALUE_OPTS = frozenset({"--log-level"})
74
81
 
75
82
  app = typer.Typer(
76
83
  name="soup",
@@ -598,10 +605,20 @@ def main(
598
605
  "--log-level",
599
606
  help="Logging tier: quiet | normal | verbose | debug",
600
607
  ),
608
+ no_audit_log: bool = typer.Option(
609
+ False,
610
+ "--no-audit-log",
611
+ help=(
612
+ "Disable the local HIPAA/SOC2 audit log for this invocation "
613
+ "(also via SOUP_NO_AUDIT_LOG=1). Default: a one-line record per "
614
+ "command under ~/.soup/audit.jsonl. v0.71.3."
615
+ ),
616
+ ),
601
617
  ):
602
618
  """Soup — fine-tune LLMs in one command."""
603
- global _verbose, _log_level
619
+ global _verbose, _log_level, _audit_disabled
604
620
  _verbose = verbose
621
+ _audit_disabled = no_audit_log
605
622
  from soup_cli.utils.log_level import (
606
623
  apply_logging_level,
607
624
  parse_log_level,
@@ -621,24 +638,114 @@ def main(
621
638
  apply_logging_level(tier)
622
639
 
623
640
 
641
+ def _split_command_args(argv: list[str]) -> tuple[str, list[str]]:
642
+ """Split ``argv`` into (command, remaining_args) for the audit record.
643
+
644
+ Skips the program name (argv[0]) and global options. Global options that
645
+ take a value (``--log-level``) consume their following token so the value
646
+ is not mistaken for the subcommand. Returns ``("(root)", [...])`` when no
647
+ subcommand is present.
648
+ """
649
+ tokens = list(argv[1:])
650
+ i = 0
651
+ while i < len(tokens):
652
+ tok = tokens[i]
653
+ if tok in _GLOBAL_VALUE_OPTS:
654
+ i += 2 # skip the option AND its value (even if the value is "-"-like)
655
+ continue
656
+ if isinstance(tok, str) and tok.startswith("-"):
657
+ i += 1
658
+ continue
659
+ return tok, tokens[i + 1:]
660
+ return "(root)", tokens
661
+
662
+
663
+ def _audit_env_opt_out() -> bool:
664
+ val = (os.environ.get("SOUP_NO_AUDIT_LOG") or "").strip().lower()
665
+ return val in {"1", "true", "yes", "on"}
666
+
667
+
668
+ def _emit_audit_event(argv: list[str], exit_code: int) -> None:
669
+ """Append one HIPAA/SOC2 audit record for this command. Best-effort.
670
+
671
+ v0.71.3 #183 — auto-instrumentation. Disabled by ``--no-audit-log`` /
672
+ ``SOUP_NO_AUDIT_LOG``. Never raises: a broken audit log must never crash
673
+ the CLI (mirrors v0.59.0 audit-log fail-soft policy).
674
+ """
675
+ if _audit_disabled or _audit_env_opt_out():
676
+ return
677
+ try:
678
+ import getpass
679
+ import platform
680
+ from datetime import datetime, timezone
681
+
682
+ from soup_cli.utils.audit_log import AuditEvent, append_audit_event
683
+
684
+ command, args = _split_command_args(argv)
685
+ command = (command or "(root)")[:64] or "(root)"
686
+ try:
687
+ operator = getpass.getuser() or "unknown"
688
+ except (OSError, KeyError, ImportError):
689
+ # getpass.getuser() can raise when no pwd / env user is resolvable.
690
+ operator = "unknown"
691
+ host = (platform.node() or "unknown")[:128] or "unknown"
692
+ operator = (operator or "unknown")[:128] or "unknown"
693
+ # Defensive re-cap, mirroring audit_log._MAX_ARGS (256) /
694
+ # _MAX_ARG_LEN (1024) so AuditEvent.__post_init__ never rejects.
695
+ capped_args = tuple(str(a)[:1024] for a in args[:256])
696
+ code = exit_code if isinstance(exit_code, int) and not isinstance(
697
+ exit_code, bool
698
+ ) else 1
699
+ ev = AuditEvent(
700
+ timestamp=datetime.now(tz=timezone.utc).isoformat(),
701
+ command=command,
702
+ args=capped_args,
703
+ exit_code=code,
704
+ host_id=host,
705
+ operator_id=operator,
706
+ )
707
+ append_audit_event(ev)
708
+ except Exception: # noqa: BLE001 — audit must never crash the CLI
709
+ pass
710
+
711
+
624
712
  def run():
625
713
  """Entry point with friendly error handling."""
626
714
  # v0.54.0 — rewrite `soup advise <data>` → `soup advise run <data>`.
627
715
  sys.argv = _rewrite_advise_argv(sys.argv)
716
+ argv_snapshot = list(sys.argv)
628
717
  try:
629
718
  app()
630
- except SystemExit:
719
+ except SystemExit as exc:
720
+ code = exc.code
721
+ if code is None:
722
+ resolved = 0
723
+ elif isinstance(code, int) and not isinstance(code, bool):
724
+ resolved = code
725
+ else:
726
+ resolved = 1
727
+ _emit_audit_event(argv_snapshot, resolved)
631
728
  raise
632
- except typer.Exit:
729
+ except typer.Exit as exc:
730
+ # Defensive/unreachable under click standalone mode (typer.Exit is
731
+ # converted to SystemExit inside app()); kept so a future click
732
+ # behaviour change still audits exactly once.
733
+ _emit_audit_event(argv_snapshot, getattr(exc, "exit_code", 1) or 0)
633
734
  raise
634
735
  except KeyboardInterrupt:
736
+ _emit_audit_event(argv_snapshot, 130)
635
737
  console.print("\n[yellow]Interrupted.[/]")
636
738
  sys.exit(130)
637
739
  except Exception as exc:
740
+ _emit_audit_event(argv_snapshot, 1)
638
741
  from soup_cli.utils.errors import format_friendly_error
639
742
 
640
743
  format_friendly_error(exc, verbose=_verbose)
641
744
  sys.exit(1)
745
+ else:
746
+ # Defensive/unreachable: app() raises SystemExit(0) on success under
747
+ # click standalone mode, so this normal-return path rarely fires.
748
+ _emit_audit_event(argv_snapshot, 0)
642
749
 
643
750
 
644
751
  # When invoked via `soup` entry point, use run() for error handling.