roar-cli 0.4.1__tar.gz → 0.4.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 (461) hide show
  1. {roar_cli-0.4.1 → roar_cli-0.4.3}/PKG-INFO +1 -1
  2. {roar_cli-0.4.1 → roar_cli-0.4.3}/pyproject.toml +2 -1
  3. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/publish/put_execution.py +118 -9
  4. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/publish/registration_package.py +34 -0
  5. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/publish/service.py +12 -0
  6. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/reproduce/requests.py +5 -0
  7. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/reproduce/service.py +127 -1
  8. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/run/execution.py +28 -0
  9. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/run/requests.py +1 -0
  10. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/run/service.py +8 -0
  11. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/system_labels.py +4 -0
  12. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/tags.py +12 -4
  13. roar_cli-0.4.3/roar/backends/k8s/attach.py +402 -0
  14. roar_cli-0.4.3/roar/backends/k8s/bundles.py +135 -0
  15. roar_cli-0.4.3/roar/backends/k8s/config.py +194 -0
  16. roar_cli-0.4.3/roar/backends/k8s/fragment_reconstituter.py +261 -0
  17. roar_cli-0.4.3/roar/backends/k8s/host_execution.py +196 -0
  18. roar_cli-0.4.3/roar/backends/k8s/lineage.py +144 -0
  19. roar_cli-0.4.3/roar/backends/k8s/manifest.py +756 -0
  20. roar_cli-0.4.3/roar/backends/k8s/mount_map.py +182 -0
  21. roar_cli-0.4.3/roar/backends/k8s/object_io.py +220 -0
  22. roar_cli-0.4.3/roar/backends/k8s/plugin.py +114 -0
  23. roar_cli-0.4.3/roar/backends/k8s/pod_entry.py +366 -0
  24. roar_cli-0.4.3/roar/backends/k8s/rayjob.py +230 -0
  25. roar_cli-0.4.3/roar/backends/k8s/secret_cleanup.py +105 -0
  26. roar_cli-0.4.3/roar/backends/k8s/submit.py +440 -0
  27. roar_cli-0.4.3/roar/backends/k8s/webhook.py +313 -0
  28. roar_cli-0.4.3/roar/backends/k8s/workload_wait.py +133 -0
  29. roar_cli-0.4.3/roar/backends/osmo/export.py +48 -0
  30. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/backends/ray/fragment_reconstituter.py +22 -0
  31. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/backends/ray/roar_worker.py +86 -33
  32. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/backends/ray/runtime_hooks.py +67 -3
  33. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/backends/ray/submit.py +2 -1
  34. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/command_registry.py +3 -0
  35. roar_cli-0.4.3/roar/cli/commands/k8s.py +226 -0
  36. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/commands/register.py +43 -13
  37. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/commands/reproduce.py +16 -0
  38. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/commands/run.py +16 -0
  39. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/context.py +15 -0
  40. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/core/models/provenance.py +4 -0
  41. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/core/models/run.py +3 -0
  42. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/db/services/job_recording.py +7 -3
  43. {roar_cli-0.4.1/roar/backends/osmo → roar_cli-0.4.3/roar/execution/fragments}/export.py +32 -13
  44. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/fragments/lineage.py +12 -6
  45. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/fragments/models.py +18 -0
  46. roar_cli-0.4.3/roar/execution/fragments/sessions.py +83 -0
  47. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/fragments/transport.py +19 -2
  48. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/framework/registry.py +63 -2
  49. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/provenance/assembler.py +5 -0
  50. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/provenance/runtime_collector.py +74 -0
  51. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/recording/job_recording.py +1 -0
  52. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/runtime/coordinator.py +4 -0
  53. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/runtime/inject/sitecustomize.py +11 -0
  54. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/runtime/worker_bootstrap.py +22 -0
  55. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/glaas/__init__.py +1 -0
  56. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/glaas/client.py +5 -0
  57. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/glaas/fragment_streamer.py +66 -3
  58. roar_cli-0.4.3/roar/integrations/wandb_trackio.py +233 -0
  59. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/presenters/show_renderer.py +8 -0
  60. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/publish_auth.py +14 -1
  61. roar_cli-0.4.3/roar/tui/screens/__init__.py +0 -0
  62. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/services/proxy/src/main.rs +12 -0
  63. roar_cli-0.4.1/roar/execution/fragments/sessions.py +0 -38
  64. {roar_cli-0.4.1 → roar_cli-0.4.3}/LICENSE +0 -0
  65. {roar_cli-0.4.1 → roar_cli-0.4.3}/README.md +0 -0
  66. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/__init__.py +0 -0
  67. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/__main__.py +0 -0
  68. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/analyzers/__init__.py +0 -0
  69. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/analyzers/base.py +0 -0
  70. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/analyzers/experiment_trackers.py +0 -0
  71. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/__init__.py +0 -0
  72. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/composite/__init__.py +0 -0
  73. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/composite/canonical.py +0 -0
  74. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/composite/detect.py +0 -0
  75. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/composite/qualifying.py +0 -0
  76. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/get/__init__.py +0 -0
  77. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/get/requests.py +0 -0
  78. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/get/results.py +0 -0
  79. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/get/service.py +0 -0
  80. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/get/transfer.py +0 -0
  81. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/git.py +0 -0
  82. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/label_rendering.py +0 -0
  83. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/labels.py +0 -0
  84. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/lookup/__init__.py +0 -0
  85. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/lookup/models.py +0 -0
  86. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/lookup/policy.py +0 -0
  87. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/lookup/refs.py +0 -0
  88. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/lookup/remote_artifacts.py +0 -0
  89. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/lookup/runner.py +0 -0
  90. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/publish/__init__.py +0 -0
  91. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/publish/anchor_attribution.py +0 -0
  92. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/publish/blake3_upgrade.py +0 -0
  93. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/publish/collection.py +0 -0
  94. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/publish/composite_builder.py +0 -0
  95. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/publish/composites.py +0 -0
  96. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/publish/datasets.py +0 -0
  97. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/publish/form_composites.py +0 -0
  98. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/publish/git_remote.py +0 -0
  99. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/publish/job_links.py +0 -0
  100. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/publish/job_preparation.py +0 -0
  101. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/publish/lineage.py +0 -0
  102. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/publish/lineage_composite_formation.py +0 -0
  103. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/publish/lineage_composites.py +0 -0
  104. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/publish/metadata.py +0 -0
  105. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/publish/put_composites.py +0 -0
  106. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/publish/put_preparation.py +0 -0
  107. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/publish/register_execution.py +0 -0
  108. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/publish/register_preparation.py +0 -0
  109. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/publish/register_preview_jobs.py +0 -0
  110. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/publish/register_tag_push.py +0 -0
  111. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/publish/registration.py +0 -0
  112. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/publish/remote_job_uids.py +0 -0
  113. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/publish/remote_registry.py +0 -0
  114. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/publish/requests.py +0 -0
  115. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/publish/results.py +0 -0
  116. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/publish/runtime.py +0 -0
  117. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/publish/secrets.py +0 -0
  118. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/publish/session.py +0 -0
  119. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/publish/source_resolution.py +0 -0
  120. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/publish/targets.py +0 -0
  121. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/publish/view_edges.py +0 -0
  122. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/query/__init__.py +0 -0
  123. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/query/dag.py +0 -0
  124. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/query/db_status.py +0 -0
  125. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/query/diff.py +0 -0
  126. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/query/diff_engine.py +0 -0
  127. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/query/diff_graph.py +0 -0
  128. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/query/diff_refs.py +0 -0
  129. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/query/git_readiness.py +0 -0
  130. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/query/inputs.py +0 -0
  131. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/query/label.py +0 -0
  132. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/query/lineage.py +0 -0
  133. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/query/log.py +0 -0
  134. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/query/requests.py +0 -0
  135. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/query/results.py +0 -0
  136. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/query/show.py +0 -0
  137. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/query/status.py +0 -0
  138. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/query/tag.py +0 -0
  139. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/reproduce/__init__.py +0 -0
  140. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/reproduce/environment.py +0 -0
  141. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/reproduce/lookup.py +0 -0
  142. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/reproduce/results.py +0 -0
  143. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/reproducibility/__init__.py +0 -0
  144. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/reproducibility/report.py +0 -0
  145. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/run/__init__.py +0 -0
  146. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/run/dag_references.py +0 -0
  147. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/run/dirty_tree_classify.py +0 -0
  148. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/run/dirty_tree_error.py +0 -0
  149. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/run/gitignore_suggest.py +0 -0
  150. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/run/output_followup.py +0 -0
  151. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/run/verbosity.py +0 -0
  152. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/workflow/__init__.py +0 -0
  153. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/workflow/requests.py +0 -0
  154. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/workflow/results.py +0 -0
  155. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/application/workflow/service.py +0 -0
  156. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/auth_store.py +0 -0
  157. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/backends/__init__.py +0 -0
  158. {roar_cli-0.4.1/roar/tui/screens → roar_cli-0.4.3/roar/backends/k8s}/__init__.py +0 -0
  159. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/backends/local/__init__.py +0 -0
  160. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/backends/local/plugin.py +0 -0
  161. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/backends/osmo/__init__.py +0 -0
  162. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/backends/osmo/config.py +0 -0
  163. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/backends/osmo/host_execution.py +0 -0
  164. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/backends/osmo/lineage.py +0 -0
  165. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/backends/osmo/plugin.py +0 -0
  166. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/backends/osmo/runtime_bundle.py +0 -0
  167. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/backends/osmo/submit.py +0 -0
  168. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/backends/osmo/workflow.py +0 -0
  169. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/backends/ray/__init__.py +0 -0
  170. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/backends/ray/_agent_names.py +0 -0
  171. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/backends/ray/collector.py +0 -0
  172. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/backends/ray/config.py +0 -0
  173. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/backends/ray/constants.py +0 -0
  174. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/backends/ray/env_contract.py +0 -0
  175. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/backends/ray/fragment.py +0 -0
  176. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/backends/ray/node_agent.py +0 -0
  177. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/backends/ray/plugin.py +0 -0
  178. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/backends/ray/proxy_fragments.py +0 -0
  179. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/backends/ray/s3_key_paths.py +0 -0
  180. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/backends/ray/submit_context.py +0 -0
  181. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/__init__.py +0 -0
  182. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/_format.py +0 -0
  183. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/_tag_kinds.py +0 -0
  184. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/commands/__init__.py +0 -0
  185. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/commands/auth.py +0 -0
  186. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/commands/build.py +0 -0
  187. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/commands/config.py +0 -0
  188. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/commands/dag.py +0 -0
  189. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/commands/db.py +0 -0
  190. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/commands/diff.py +0 -0
  191. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/commands/env.py +0 -0
  192. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/commands/export_registration_package.py +0 -0
  193. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/commands/filter.py +0 -0
  194. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/commands/get.py +0 -0
  195. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/commands/init.py +0 -0
  196. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/commands/init_agents.py +0 -0
  197. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/commands/inputs.py +0 -0
  198. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/commands/label.py +0 -0
  199. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/commands/lineage.py +0 -0
  200. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/commands/log.py +0 -0
  201. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/commands/login.py +0 -0
  202. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/commands/logout.py +0 -0
  203. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/commands/osmo.py +0 -0
  204. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/commands/pop.py +0 -0
  205. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/commands/projects.py +0 -0
  206. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/commands/proxy.py +0 -0
  207. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/commands/put.py +0 -0
  208. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/commands/reset.py +0 -0
  209. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/commands/scope.py +0 -0
  210. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/commands/session.py +0 -0
  211. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/commands/show.py +0 -0
  212. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/commands/status.py +0 -0
  213. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/commands/tag.py +0 -0
  214. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/commands/telemetry.py +0 -0
  215. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/commands/tracer.py +0 -0
  216. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/commands/tui.py +0 -0
  217. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/commands/whoami.py +0 -0
  218. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/commands/workflow.py +0 -0
  219. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/decorators.py +0 -0
  220. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/publish_intent.py +0 -0
  221. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/templates/agents/SKILL.md.tmpl +0 -0
  222. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/cli/templates/agents/agents_section.md.tmpl +0 -0
  223. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/core/__init__.py +0 -0
  224. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/core/bootstrap.py +0 -0
  225. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/core/canonical_session.py +0 -0
  226. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/core/digests.py +0 -0
  227. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/core/dto/__init__.py +0 -0
  228. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/core/dto/registration.py +0 -0
  229. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/core/exceptions.py +0 -0
  230. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/core/interfaces/__init__.py +0 -0
  231. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/core/interfaces/config.py +0 -0
  232. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/core/interfaces/lineage.py +0 -0
  233. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/core/interfaces/logger.py +0 -0
  234. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/core/interfaces/presenter.py +0 -0
  235. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/core/interfaces/provenance.py +0 -0
  236. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/core/interfaces/registration.py +0 -0
  237. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/core/interfaces/repositories.py +0 -0
  238. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/core/interfaces/reproduction.py +0 -0
  239. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/core/interfaces/run.py +0 -0
  240. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/core/interfaces/services.py +0 -0
  241. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/core/interfaces/telemetry.py +0 -0
  242. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/core/interfaces/vcs.py +0 -0
  243. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/core/label_constants.py +0 -0
  244. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/core/label_origins.py +0 -0
  245. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/core/logging.py +0 -0
  246. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/core/models/__init__.py +0 -0
  247. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/core/models/artifact.py +0 -0
  248. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/core/models/base.py +0 -0
  249. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/core/models/dag.py +0 -0
  250. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/core/models/dataset_identifier.py +0 -0
  251. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/core/models/glaas.py +0 -0
  252. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/core/models/job.py +0 -0
  253. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/core/models/lineage.py +0 -0
  254. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/core/models/session.py +0 -0
  255. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/core/models/telemetry.py +0 -0
  256. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/core/models/vcs.py +0 -0
  257. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/core/operation_metadata.py +0 -0
  258. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/core/session_hash.py +0 -0
  259. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/core/step_name.py +0 -0
  260. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/core/tracer_modes.py +0 -0
  261. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/core/validation.py +0 -0
  262. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/db/__init__.py +0 -0
  263. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/db/context.py +0 -0
  264. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/db/engine.py +0 -0
  265. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/db/hashing/__init__.py +0 -0
  266. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/db/hashing/backend.py +0 -0
  267. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/db/hashing/blake3.py +0 -0
  268. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/db/models.py +0 -0
  269. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/db/query_context.py +0 -0
  270. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/db/repositories/__init__.py +0 -0
  271. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/db/repositories/artifact.py +0 -0
  272. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/db/repositories/collection.py +0 -0
  273. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/db/repositories/composite.py +0 -0
  274. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/db/repositories/hash_cache.py +0 -0
  275. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/db/repositories/job.py +0 -0
  276. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/db/repositories/label.py +0 -0
  277. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/db/repositories/session.py +0 -0
  278. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/db/schema.py +0 -0
  279. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/db/services/__init__.py +0 -0
  280. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/db/services/hashing.py +0 -0
  281. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/db/services/lineage.py +0 -0
  282. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/db/services/session.py +0 -0
  283. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/db/step_priority.py +0 -0
  284. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/__init__.py +0 -0
  285. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/cluster/__init__.py +0 -0
  286. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/cluster/bridge.py +0 -0
  287. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/cluster/proxy.py +0 -0
  288. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/cluster/proxy_config.py +0 -0
  289. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/fragments/__init__.py +0 -0
  290. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/fragments/reconstitution.py +0 -0
  291. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/framework/__init__.py +0 -0
  292. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/framework/contract.py +0 -0
  293. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/framework/planning.py +0 -0
  294. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/framework/runtime_imports.py +0 -0
  295. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/provenance/__init__.py +0 -0
  296. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/provenance/build_pip_collector.py +0 -0
  297. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/provenance/build_tool_collector.py +0 -0
  298. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/provenance/data_loader.py +0 -0
  299. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/provenance/file_filter.py +0 -0
  300. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/provenance/package_collector.py +0 -0
  301. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/provenance/process_summarizer.py +0 -0
  302. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/provenance/service.py +0 -0
  303. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/recording/__init__.py +0 -0
  304. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/recording/dataset_identifier.py +0 -0
  305. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/recording/dataset_metadata.py +0 -0
  306. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/recording/dataset_profile.py +0 -0
  307. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/reproduction/__init__.py +0 -0
  308. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/reproduction/environment_setup.py +0 -0
  309. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/reproduction/installers.py +0 -0
  310. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/reproduction/pipeline_executor.py +0 -0
  311. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/reproduction/pipeline_metadata.py +0 -0
  312. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/runtime/__init__.py +0 -0
  313. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/runtime/abi_probe.py +0 -0
  314. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/runtime/active_runs.py +0 -0
  315. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/runtime/backup.py +0 -0
  316. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/runtime/driver_entrypoint.py +0 -0
  317. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/runtime/errors.py +0 -0
  318. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/runtime/host_execution.py +0 -0
  319. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/runtime/inject/__init__.py +0 -0
  320. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/runtime/inject/support.py +0 -0
  321. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/runtime/inject/tracker.py +0 -0
  322. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/runtime/lazy_install.py +0 -0
  323. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/runtime/proxy_resource.py +0 -0
  324. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/runtime/resources.py +0 -0
  325. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/runtime/signal_handler.py +0 -0
  326. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/runtime/tracer.py +0 -0
  327. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/runtime/tracer_backends.py +0 -0
  328. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/execution/runtime/tracer_banner.py +0 -0
  329. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/filters/__init__.py +0 -0
  330. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/filters/files.py +0 -0
  331. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/filters/omit.py +0 -0
  332. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/glaas_auth.py +0 -0
  333. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/glaas_client.py +0 -0
  334. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/__init__.py +0 -0
  335. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/bootstrap.py +0 -0
  336. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/config/__init__.py +0 -0
  337. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/config/access.py +0 -0
  338. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/config/loader.py +0 -0
  339. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/config/raw.py +0 -0
  340. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/config/schema.py +0 -0
  341. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/discovery.py +0 -0
  342. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/download/__init__.py +0 -0
  343. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/download/base.py +0 -0
  344. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/download/gcs.py +0 -0
  345. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/download/get.py +0 -0
  346. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/download/hf.py +0 -0
  347. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/download/http.py +0 -0
  348. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/download/noop.py +0 -0
  349. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/download/s3.py +0 -0
  350. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/git/__init__.py +0 -0
  351. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/git/base.py +0 -0
  352. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/git/context.py +0 -0
  353. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/git/provider.py +0 -0
  354. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/glaas/auth.py +0 -0
  355. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/glaas/registration/__init__.py +0 -0
  356. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/glaas/registration/_artifact_ref.py +0 -0
  357. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/glaas/registration/artifact.py +0 -0
  358. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/glaas/registration/coordinator.py +0 -0
  359. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/glaas/registration/job.py +0 -0
  360. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/glaas/registration/session.py +0 -0
  361. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/glaas/transport.py +0 -0
  362. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/registry.py +0 -0
  363. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/resolution.py +0 -0
  364. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/storage/__init__.py +0 -0
  365. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/storage/base.py +0 -0
  366. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/storage/gcs.py +0 -0
  367. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/storage/hf.py +0 -0
  368. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/storage/memory.py +0 -0
  369. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/storage/noop.py +0 -0
  370. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/storage/publish.py +0 -0
  371. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/storage/s3.py +0 -0
  372. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/telemetry/__init__.py +0 -0
  373. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/telemetry/base.py +0 -0
  374. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/integrations/telemetry/wandb.py +0 -0
  375. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/presenters/__init__.py +0 -0
  376. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/presenters/console.py +0 -0
  377. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/presenters/dag_data_builder.py +0 -0
  378. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/presenters/dag_renderer.py +0 -0
  379. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/presenters/diff_renderer.py +0 -0
  380. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/presenters/formatting.py +0 -0
  381. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/presenters/null.py +0 -0
  382. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/presenters/run_report.py +0 -0
  383. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/presenters/spinner.py +0 -0
  384. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/presenters/terminal.py +0 -0
  385. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/require.py +0 -0
  386. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/scope_config.py +0 -0
  387. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/telemetry/__init__.py +0 -0
  388. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/telemetry/_io.py +0 -0
  389. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/telemetry/capabilities.py +0 -0
  390. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/telemetry/config.py +0 -0
  391. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/telemetry/hooks.py +0 -0
  392. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/telemetry/install.py +0 -0
  393. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/telemetry/paths.py +0 -0
  394. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/telemetry/payload.py +0 -0
  395. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/telemetry/queue.py +0 -0
  396. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/telemetry/stats.py +0 -0
  397. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/telemetry/uploader.py +0 -0
  398. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/tui/__init__.py +0 -0
  399. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/tui/app.py +0 -0
  400. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/tui/data.py +0 -0
  401. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/tui/screens/config_editor.py +0 -0
  402. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/tui/screens/label_editor.py +0 -0
  403. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/tui/screens/launcher.py +0 -0
  404. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/tui/screens/log.py +0 -0
  405. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/tui/screens/main.py +0 -0
  406. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/tui/screens/search.py +0 -0
  407. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/tui/screens/session_picker.py +0 -0
  408. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/tui/tmux.py +0 -0
  409. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/tui/widgets/__init__.py +0 -0
  410. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/tui/widgets/detail.py +0 -0
  411. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/utils/__init__.py +0 -0
  412. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/utils/cloud.py +0 -0
  413. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/utils/git_url.py +0 -0
  414. {roar_cli-0.4.1 → roar_cli-0.4.3}/roar/version_check.py +0 -0
  415. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/Cargo.lock +0 -0
  416. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/Cargo.toml +0 -0
  417. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/crates/artifact-hash-core/Cargo.toml +0 -0
  418. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/crates/artifact-hash-core/src/lib.rs +0 -0
  419. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/crates/artifact-hash-py/Cargo.toml +0 -0
  420. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/crates/artifact-hash-py/src/lib.rs +0 -0
  421. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/crates/tracer-fd/Cargo.toml +0 -0
  422. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/crates/tracer-fd/src/lib.rs +0 -0
  423. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/crates/tracer-runtime/Cargo.toml +0 -0
  424. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/crates/tracer-runtime/src/lib.rs +0 -0
  425. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/crates/tracer-schema/Cargo.toml +0 -0
  426. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/crates/tracer-schema/src/lib.rs +0 -0
  427. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/services/proxy/Cargo.lock +0 -0
  428. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/services/proxy/Cargo.toml +0 -0
  429. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/services/proxy/src/forward.rs +0 -0
  430. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/services/proxy/src/s3.rs +0 -0
  431. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/tracers/ebpf/common/Cargo.toml +0 -0
  432. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/tracers/ebpf/common/src/lib.rs +0 -0
  433. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/tracers/ebpf/probe/Cargo.toml +0 -0
  434. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/tracers/ebpf/probe/rust-toolchain.toml +0 -0
  435. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/tracers/ebpf/probe/src/main.rs +0 -0
  436. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/tracers/ebpf/userspace/Cargo.toml +0 -0
  437. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/tracers/ebpf/userspace/build.rs +0 -0
  438. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/tracers/ebpf/userspace/src/attach.rs +0 -0
  439. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/tracers/ebpf/userspace/src/bin/roard.rs +0 -0
  440. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/tracers/ebpf/userspace/src/client.rs +0 -0
  441. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/tracers/ebpf/userspace/src/daemon.rs +0 -0
  442. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/tracers/ebpf/userspace/src/events.rs +0 -0
  443. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/tracers/ebpf/userspace/src/ipc.rs +0 -0
  444. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/tracers/ebpf/userspace/src/lib.rs +0 -0
  445. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/tracers/ebpf/userspace/src/main.rs +0 -0
  446. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/tracers/ebpf/userspace/src/state.rs +0 -0
  447. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/tracers/preload/Cargo.toml +0 -0
  448. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/tracers/preload/build.rs +0 -0
  449. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/tracers/preload/src/bin/io_fixture.rs +0 -0
  450. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/tracers/preload/src/interpose.c +0 -0
  451. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/tracers/preload/src/ipc.rs +0 -0
  452. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/tracers/preload/src/lib.rs +0 -0
  453. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/tracers/preload/src/main.rs +0 -0
  454. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/tracers/preload/tests/comprehensive.rs +0 -0
  455. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/tracers/preload/tests/standalone.rs +0 -0
  456. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/tracers/ptrace/Cargo.toml +0 -0
  457. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/tracers/ptrace/rustfmt.toml +0 -0
  458. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/tracers/ptrace/src/arch.rs +0 -0
  459. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/tracers/ptrace/src/main.rs +0 -0
  460. {roar_cli-0.4.1 → roar_cli-0.4.3}/rust/tracers/ptrace/src/seccomp.rs +0 -0
  461. {roar_cli-0.4.1 → roar_cli-0.4.3}/scripts/sync_packaged_rust_artifacts.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: roar-cli
3
- Version: 0.4.1
3
+ Version: 0.4.3
4
4
  Classifier: Development Status :: 3 - Alpha
5
5
  Classifier: Intended Audience :: Developers
6
6
  Classifier: Intended Audience :: Science/Research
@@ -5,7 +5,7 @@ build-backend = "maturin"
5
5
 
6
6
  [project]
7
7
  name = "roar-cli"
8
- version = "0.4.1"
8
+ version = "0.4.3"
9
9
  description = "Reproducibility and provenance tracker for ML training pipelines"
10
10
  authors = [
11
11
  { name="TReqs Team", email="info@treqs.ai" }
@@ -124,6 +124,7 @@ markers = [
124
124
  "diagnostic: Opt-in diagnostics or aspirational performance budgets outside the default gate",
125
125
  "large_pipeline: Stress-style pipeline coverage with larger DAG fixtures",
126
126
  "osmo_e2e: OSMO end-to-end tests requiring a Docker Compose managed KIND harness",
127
+ "k8s_e2e: Kubernetes end-to-end tests requiring the KIND harness (tests/backends/k8s)",
127
128
  "ray_e2e: Ray end-to-end tests requiring a running Docker cluster",
128
129
  "ray_contract: User-facing Ray contract tests using `roar run ray job submit ...`",
129
130
  "ray_diagnostic: Diagnostic Ray tests that intentionally inspect internal runtime details",
@@ -9,6 +9,7 @@ roar put ALWAYS registers lineage with GLaaS. This is not optional.
9
9
 
10
10
  from __future__ import annotations
11
11
 
12
+ import shlex
12
13
  import time
13
14
  from dataclasses import dataclass, field
14
15
  from pathlib import Path
@@ -33,6 +34,7 @@ from ...application.publish.remote_job_uids import (
33
34
  from ...application.publish.session import build_staged_lineage_counts
34
35
  from ...application.system_labels import refresh_job_system_labels
35
36
  from ...core.interfaces.registration import GitContext
37
+ from ...core.label_origins import LABEL_ORIGIN_SYSTEM
36
38
  from ...core.logging import get_logger
37
39
  from ...db.context import DatabaseContext
38
40
  from ...db.hashing import hash_files_blake3
@@ -52,6 +54,47 @@ from .put_composites import (
52
54
  from .results import PutCompositeRegistration, PutDryRunItem, PutUploadedFile
53
55
 
54
56
 
57
+ def build_put_command(
58
+ sources: list[str],
59
+ destination: str | None,
60
+ *,
61
+ message: str,
62
+ public: bool = True,
63
+ anonymous: bool = False,
64
+ no_tag: bool = False,
65
+ as_dataset: bool = False,
66
+ step_name: str | None = None,
67
+ ) -> str:
68
+ """Reconstruct a faithful ``roar put`` command string for the job record.
69
+
70
+ The recorded command drives ``roar reproduce``, so it must include the
71
+ destination and every provenance-relevant flag — not just the sources and
72
+ message. Interaction/mode flags (``--yes``, ``--dry-run``) are intentionally
73
+ omitted: they control confirmation/preview, not the published result.
74
+ """
75
+ parts = ["roar", "put"]
76
+ if sources:
77
+ parts.extend(shlex.quote(s) for s in sources)
78
+ else:
79
+ parts.append("(session outputs)")
80
+ if destination:
81
+ parts.append(shlex.quote(destination))
82
+ if anonymous:
83
+ parts.append("--anonymous")
84
+ elif public is False:
85
+ parts.append("--private")
86
+ elif public:
87
+ parts.append("--public")
88
+ if no_tag:
89
+ parts.append("--no-tag")
90
+ if as_dataset:
91
+ parts.append("--as-dataset")
92
+ if step_name:
93
+ parts.extend(["--step-name", shlex.quote(step_name)])
94
+ parts.extend(["-m", shlex.quote(message)])
95
+ return " ".join(parts)
96
+
97
+
55
98
  def _upload_progress_message(done: int, total: int, uploaded_bytes: int) -> str:
56
99
  """Status line for the upload spinner, e.g. ``Uploading 12/100 files · 1.10 GB``."""
57
100
  return f"Uploading {done}/{total} files · {uploaded_bytes / 1e9:.2f} GB"
@@ -145,6 +188,7 @@ class PutService:
145
188
  git_commit: str | None = None,
146
189
  git_tag: str | None = None,
147
190
  declared: bool = False,
191
+ command: str | None = None,
148
192
  ) -> PutResult:
149
193
  """
150
194
  Execute a put operation.
@@ -266,6 +310,13 @@ class PutService:
266
310
  artifact_hashes = [u.hash for u in uploads]
267
311
  artifacts_info = [(u.artifact_id, u.local_path) for u in uploads]
268
312
 
313
+ # Record each uploaded artifact's distribution URL as a reserved system
314
+ # label, scoped to this publication, so GLaaS can surface it as the
315
+ # AI-BOM downloadLocation (see _set_publish_distribution_labels).
316
+ self._set_publish_distribution_labels(
317
+ uploads, normalize_registration_source_type(destination_type)
318
+ )
319
+
269
320
  self._logger.debug(
270
321
  "Upload complete: %d file(s), collecting lineage for hashes: %s",
271
322
  len(uploaded_files),
@@ -294,6 +345,7 @@ class PutService:
294
345
  git_context=git_context,
295
346
  sources=sources,
296
347
  message=message,
348
+ command=command,
297
349
  uploads=uploads,
298
350
  uploaded_files=uploaded_files,
299
351
  artifacts_info=artifacts_info,
@@ -416,9 +468,10 @@ class PutService:
416
468
  for item in composite_registrations
417
469
  ]
418
470
 
419
- # Build command string
420
- source_str = " ".join(sources) if sources else "(session outputs)"
421
- command = f'roar put {source_str} -m "{message}"'
471
+ # Build command string. Prefer the faithful command (destination + flags)
472
+ # supplied by the caller; fall back to a destination-aware reconstruction.
473
+ if command is None:
474
+ command = build_put_command(sources, self._destination, message=message)
422
475
 
423
476
  # Build metadata
424
477
  metadata_json = build_put_operation_metadata_json(
@@ -493,6 +546,7 @@ class PutService:
493
546
  job_uid=job_uid,
494
547
  remote_job_uid=job_uid,
495
548
  registration_errors=registration_result.errors,
549
+ uploads=uploads,
496
550
  )
497
551
 
498
552
  registration_error = (
@@ -551,6 +605,7 @@ class PutService:
551
605
  git_context: GitContext,
552
606
  sources: list[str],
553
607
  message: str,
608
+ command: str | None = None,
554
609
  uploads: list[_UploadedArtifact],
555
610
  uploaded_files: list[PutUploadedFile],
556
611
  artifacts_info: list[tuple[str, str]],
@@ -571,8 +626,8 @@ class PutService:
571
626
  registration_errors: list[str] = []
572
627
  lineage_composite_registrations: list[dict[str, Any]] = []
573
628
  composite_registrations: list[dict[str, Any]] = []
574
- source_str = " ".join(sources) if sources else "(session outputs)"
575
- command = f'roar put {source_str} -m "{message}"'
629
+ if command is None:
630
+ command = build_put_command(sources, self._destination, message=message)
576
631
  source_type = normalize_registration_source_type(destination_type)
577
632
 
578
633
  provisional_metadata_json = build_put_operation_metadata_json(
@@ -764,6 +819,7 @@ class PutService:
764
819
  job_uid=job_uid,
765
820
  remote_job_uid=remote_put_job_uid,
766
821
  registration_errors=registration_errors,
822
+ uploads=uploads,
767
823
  )
768
824
 
769
825
  composite_result_items = [
@@ -912,8 +968,12 @@ class PutService:
912
968
  "size": size,
913
969
  "source_type": source_type,
914
970
  }
915
- if uploaded.remote_url:
916
- entry["source_url"] = uploaded.remote_url
971
+ # Deliberately do NOT record the upload destination as the artifact's
972
+ # global ``source_url`` here. That row is content-addressed and shared
973
+ # across orgs, so a per-publication URL would leak between tenants.
974
+ # The download location is published instead as a session-scoped
975
+ # ``roar.distribution.url`` label (see _set_publish_distribution_labels),
976
+ # which both the registration-session and this legacy inline path emit.
917
977
 
918
978
  payloads.append(entry)
919
979
 
@@ -994,6 +1054,48 @@ class PutService:
994
1054
  return False
995
1055
  return True
996
1056
 
1057
+ def _set_publish_distribution_labels(
1058
+ self,
1059
+ uploads: list[_UploadedArtifact],
1060
+ source_type: str | None,
1061
+ ) -> None:
1062
+ """Record each uploaded artifact's distribution URL as a reserved system
1063
+ label (``roar.distribution.url``), scoped to this publication.
1064
+
1065
+ GLaaS reads this as the artifact's AI-BOM ``downloadLocation``. Because
1066
+ the label lives on the ``(artifact, session)`` scope rather than the
1067
+ global content-addressed artifact row, two orgs publishing identical
1068
+ bytes each carry their own download location — no cross-tenant bleed.
1069
+ Gated on a recognized remote ``source_type`` so we never assert a
1070
+ distribution URL for a non-remote destination (e.g. ``memory://``).
1071
+ """
1072
+ if not source_type:
1073
+ return
1074
+ labels_repo = getattr(self._db, "labels", None)
1075
+ if labels_repo is None:
1076
+ return
1077
+ for uploaded in uploads:
1078
+ if not uploaded.remote_url or not uploaded.artifact_id:
1079
+ continue
1080
+ current = labels_repo.get_current("artifact", artifact_id=uploaded.artifact_id)
1081
+ metadata = current.get("metadata") if isinstance(current, dict) else None
1082
+ metadata = dict(metadata) if isinstance(metadata, dict) else {}
1083
+ roar_ns = metadata.get("roar")
1084
+ roar_ns = dict(roar_ns) if isinstance(roar_ns, dict) else {}
1085
+ distribution = roar_ns.get("distribution")
1086
+ distribution = dict(distribution) if isinstance(distribution, dict) else {}
1087
+ if distribution.get("url") == uploaded.remote_url:
1088
+ continue # already recorded — avoid a redundant label version
1089
+ distribution["url"] = uploaded.remote_url
1090
+ roar_ns["distribution"] = distribution
1091
+ metadata["roar"] = roar_ns
1092
+ labels_repo.create_version(
1093
+ "artifact",
1094
+ metadata,
1095
+ artifact_id=uploaded.artifact_id,
1096
+ write_origin=LABEL_ORIGIN_SYSTEM,
1097
+ )
1098
+
997
1099
  def _sync_put_job_labels_with_glaas(
998
1100
  self,
999
1101
  *,
@@ -1003,15 +1105,22 @@ class PutService:
1003
1105
  job_uid: str,
1004
1106
  remote_job_uid: str,
1005
1107
  registration_errors: list[str],
1108
+ uploads: list[_UploadedArtifact] | None = None,
1006
1109
  ) -> None:
1007
- """Sync the local current label document for the publish-time put job."""
1110
+ """Sync the local current label document for the publish-time put job
1111
+ and its published artifacts (carrying ``roar.distribution.url``)."""
1112
+ artifacts = (
1113
+ [{"id": u.artifact_id, "hash": u.hash} for u in uploads if u.artifact_id and u.hash]
1114
+ if uploads
1115
+ else []
1116
+ )
1008
1117
  sync_publish_labels(
1009
1118
  glaas_client=glaas_client,
1010
1119
  db_ctx=self._db,
1011
1120
  session_id=None,
1012
1121
  session_hash=session_hash,
1013
1122
  jobs=[{"id": job_id, "job_uid": job_uid, "remote_job_uid": remote_job_uid}],
1014
- artifacts=[],
1123
+ artifacts=artifacts,
1015
1124
  errors=registration_errors,
1016
1125
  )
1017
1126
 
@@ -206,6 +206,8 @@ def build_registration_package(
206
206
  if composites:
207
207
  package["composites"] = composites
208
208
 
209
+ if labels:
210
+ labels = _drop_labels_for_absent_jobs(labels, job_records)
209
211
  if labels:
210
212
  filtered_labels, label_detections = _filter_label_secrets(labels, omit_filter)
211
213
  package["labels"] = filtered_labels
@@ -292,6 +294,38 @@ def _apply_redaction(
292
294
  )
293
295
 
294
296
 
297
+ def _drop_labels_for_absent_jobs(
298
+ labels: list[dict[str, Any]],
299
+ job_records: list[dict[str, Any]],
300
+ ) -> list[dict[str, Any]]:
301
+ """Drop job-scoped labels whose target job is not in the package.
302
+
303
+ Labels are collected from the raw lineage, but the package's jobs are
304
+ noise-filtered by ``normalize_jobs_for_registration``. A job label left
305
+ pointing at a dropped job makes the package internally inconsistent — GLaaS
306
+ rejects it on publish with "Package label references a job not in the
307
+ package". The job label's target reaches the publish side through the job
308
+ record's ``job_uid`` (GLaaS's ``sourceUid``), so match on that. Non-job
309
+ labels (dag, artifact) are unaffected.
310
+ """
311
+ package_job_uids = {str(job.get("job_uid")) for job in job_records if job.get("job_uid")}
312
+ kept: list[dict[str, Any]] = []
313
+ dropped = 0
314
+ for label in labels:
315
+ if str(label.get("entity_type")) == "job":
316
+ job_uid = label.get("job_uid")
317
+ if not isinstance(job_uid, str) or job_uid not in package_job_uids:
318
+ dropped += 1
319
+ continue
320
+ kept.append(label)
321
+ if dropped:
322
+ get_logger().debug(
323
+ "Dropped %d job label(s) referencing jobs not in the registration package",
324
+ dropped,
325
+ )
326
+ return kept
327
+
328
+
295
329
  def _filter_label_secrets(
296
330
  labels: list[dict[str, Any]],
297
331
  omit_filter: OmitFilter | None,
@@ -894,6 +894,8 @@ def put_artifacts(request: PutRequest) -> PutResponse:
894
894
  )
895
895
  put_commit_on_remote = is_shareable_remote(prepared.git_context.repo)
896
896
 
897
+ from .put_execution import build_put_command
898
+
897
899
  result = service.put_prepared(
898
900
  prepared=prepared,
899
901
  sources=request.sources,
@@ -902,6 +904,16 @@ def put_artifacts(request: PutRequest) -> PutResponse:
902
904
  git_commit=git_commit,
903
905
  git_tag=expected_tag,
904
906
  declared=request.as_dataset,
907
+ command=build_put_command(
908
+ request.sources,
909
+ request.destination,
910
+ message=request.message,
911
+ public=request.public,
912
+ anonymous=request.anonymous,
913
+ no_tag=request.no_tag,
914
+ as_dataset=request.as_dataset,
915
+ step_name=request.step_name,
916
+ ),
905
917
  )
906
918
 
907
919
  # Apply step name label if provided.
@@ -20,3 +20,8 @@ class ReproduceRequest:
20
20
  package_sync: bool = False
21
21
  list_requirements: bool = False
22
22
  out_path: str | None = None
23
+ # Skip publish (`roar put`) steps — for third-party reproduction that
24
+ # rebuilds the artifact without re-publishing to the owner's destination.
25
+ no_puts: bool = False
26
+ # Emit an editable reproduction shell script instead of previewing/running.
27
+ emit_script: bool = False
@@ -4,6 +4,7 @@ from __future__ import annotations
4
4
 
5
5
  import json
6
6
  import re
7
+ import shlex
7
8
  from contextlib import contextmanager
8
9
  from pathlib import Path
9
10
  from typing import TYPE_CHECKING, Literal
@@ -42,7 +43,7 @@ def reproduce_artifact(
42
43
  server_url = _load_server_url(request.cwd)
43
44
  glaas_client = _build_glaas_client(server_url)
44
45
 
45
- if request.out_path:
46
+ if request.out_path and not request.emit_script:
46
47
  _write_reproduction_output(
47
48
  request.hash_prefix,
48
49
  request.target_kind,
@@ -51,6 +52,9 @@ def reproduce_artifact(
51
52
  output,
52
53
  )
53
54
 
55
+ if request.emit_script and request.run_pipeline:
56
+ raise ValueError("choose either --script or --run, not both")
57
+
54
58
  pipeline, _pipeline_source = _resolve_pipeline(
55
59
  hash_prefix=request.hash_prefix,
56
60
  server_url=server_url,
@@ -58,6 +62,30 @@ def reproduce_artifact(
58
62
  glaas_client=glaas_client,
59
63
  target_kind=request.target_kind,
60
64
  )
65
+
66
+ # --no-puts: drop publish (`roar put`) steps so a third-party reproduction
67
+ # rebuilds the artifact without re-publishing to the owner's destination.
68
+ # Applied to the pipeline itself so preview, --script, and --run all agree
69
+ # (and the steps_run/steps_total accounting stays consistent).
70
+ if request.no_puts:
71
+ dropped = _drop_put_steps(pipeline)
72
+ # In --script mode stdout is the script itself; the omission is documented
73
+ # by a comment inside it, so don't pollute stdout with a notice here.
74
+ if dropped and not request.emit_script:
75
+ output.print(f"Skipping {dropped} publish (roar put) step(s) [--no-puts]")
76
+
77
+ # --script: emit an editable reproduction script instead of previewing/running.
78
+ if request.emit_script:
79
+ output.print(
80
+ build_reproduction_script(
81
+ pipeline,
82
+ request.hash_prefix,
83
+ target_kind=request.target_kind,
84
+ no_puts=request.no_puts,
85
+ )
86
+ )
87
+ return
88
+
61
89
  preview = build_preview_summary(
62
90
  pipeline,
63
91
  hash_prefix=request.hash_prefix,
@@ -357,6 +385,104 @@ def _resolve_pipeline(
357
385
  return pipeline, lookup.source
358
386
 
359
387
 
388
+ def _is_put_step(step: dict) -> bool:
389
+ """A publish step: recorded as job_type 'put' or a `roar put …` command."""
390
+ kind = step.get("job_type") or step.get("jobType")
391
+ if isinstance(kind, str) and kind.strip().lower() == "put":
392
+ return True
393
+ cmd = str(step.get("command") or "").strip()
394
+ return cmd.split()[:2] == ["roar", "put"]
395
+
396
+
397
+ def _drop_put_steps(pipeline: PipelineInfo) -> int:
398
+ """Remove publish steps from the pipeline in place; return how many were dropped."""
399
+ before = len(pipeline.run_steps)
400
+ pipeline.run_steps = [s for s in pipeline.run_steps if not _is_put_step(s)]
401
+ pipeline.total_steps = len(pipeline.build_steps) + len(pipeline.run_steps)
402
+ return before - len(pipeline.run_steps)
403
+
404
+
405
+ def build_reproduction_script(
406
+ pipeline: PipelineInfo,
407
+ hash_prefix: str,
408
+ *,
409
+ target_kind: str = "artifact",
410
+ no_puts: bool = False,
411
+ ) -> str:
412
+ """Render an editable bash reproduction script (clone → env → pipeline).
413
+
414
+ Dry by design: nothing runs until the user executes it. Mirrors what
415
+ `--run` would do, so it composes with `--no-puts` (which has already
416
+ filtered publish steps out of *pipeline*).
417
+ """
418
+ from ..tags import run_modifier_flags
419
+
420
+ lines = [
421
+ "#!/usr/bin/env bash",
422
+ f"# Reproduction script for {target_kind} {hash_prefix}",
423
+ "# Generated by `roar reproduce --script`. Dry & editable: review the steps",
424
+ "# (e.g. change --device, or run on your own infra) before executing.",
425
+ ]
426
+ if no_puts:
427
+ lines.append("# Publish (roar put) steps are omitted (--no-puts).")
428
+ lines += ["set -euo pipefail", ""]
429
+
430
+ repo = pipeline.git_repo or "<unknown-git-repo>"
431
+ lines += [
432
+ "# 1. Clone the recorded code at its exact commit",
433
+ f"git clone {shlex.quote(repo)} reproduction",
434
+ "cd reproduction",
435
+ ]
436
+ if pipeline.git_commit:
437
+ lines.append(f"git checkout {shlex.quote(pipeline.git_commit)}")
438
+ if not pipeline.single_commit:
439
+ lines.append("# NOTE: the recorded session spanned multiple commits; results may differ.")
440
+ lines.append("")
441
+
442
+ lines += [
443
+ "# 2. Recreate the Python environment",
444
+ "python3 -m venv .venv",
445
+ "source .venv/bin/activate",
446
+ ]
447
+ for block in _build_requirement_blocks(pipeline):
448
+ if not block.values:
449
+ continue
450
+ if block.label in ("Pip packages", "Build tool pip packages"):
451
+ lines.append("pip install " + " ".join(shlex.quote(v) for v in block.values))
452
+ else: # system / build-tool dpkg packages need sudo — emit as a comment
453
+ lines.append(f"# {block.label} (apt; requires sudo): " + " ".join(block.values))
454
+ lines.append("")
455
+
456
+ lines.append("# 3. Run the pipeline (recorded order)")
457
+ for step in pipeline.build_steps:
458
+ cmd = str(step.get("command") or "").strip()
459
+ if cmd:
460
+ lines.append(f"roar build {cmd}")
461
+ for step in pipeline.run_steps:
462
+ cmd = str(step.get("command") or "").strip()
463
+ if not cmd:
464
+ continue
465
+ # A step whose command is already a `roar …` invocation (e.g. `roar put`)
466
+ # is emitted as-is; other commands are wrapped in `roar run` (replaying
467
+ # any recorded run-modifiers) exactly as the executor would.
468
+ if cmd.split()[:1] == ["roar"]:
469
+ lines.append(cmd)
470
+ continue
471
+ metadata = step.get("metadata")
472
+ if isinstance(metadata, str):
473
+ try:
474
+ metadata = json.loads(metadata)
475
+ except (ValueError, TypeError):
476
+ metadata = {}
477
+ mods = (
478
+ run_modifier_flags(metadata.get("run_modifiers")) if isinstance(metadata, dict) else ""
479
+ )
480
+ prefix = f"roar run {mods}".strip()
481
+ lines.append(f"{prefix} {cmd}")
482
+ lines.append("")
483
+ return "\n".join(lines)
484
+
485
+
360
486
  def build_preview_summary(
361
487
  pipeline: PipelineInfo,
362
488
  *,
@@ -28,6 +28,32 @@ class ExecutionReport:
28
28
  setup_error: bool = False
29
29
 
30
30
 
31
+ RUN_REPORT_FILE_ENV = "ROAR_RUN_REPORT_FILE"
32
+
33
+
34
+ def write_run_report_file(report: ExecutionReport) -> None:
35
+ """Write a machine-readable run outcome when ROAR_RUN_REPORT_FILE is set.
36
+
37
+ Wrappers that cannot see past the exit code (the k8s pod entrypoint) use
38
+ ``setup_error`` to distinguish "roar failed before launching the
39
+ workload" from "the workload ran and failed" — only the former is safe
40
+ to rerun uninstrumented. Advisory only: never fails the run.
41
+ """
42
+ target = str(os.environ.get(RUN_REPORT_FILE_ENV) or "").strip()
43
+ if not target:
44
+ return
45
+ import contextlib
46
+ import json
47
+
48
+ payload = {
49
+ "exit_code": report.exit_code,
50
+ "setup_error": report.setup_error,
51
+ "tracer_backend": report.tracer_backend,
52
+ }
53
+ with contextlib.suppress(OSError):
54
+ Path(target).write_text(json.dumps(payload), encoding="utf-8")
55
+
56
+
31
57
  def validate_git_clean(
32
58
  *,
33
59
  verb: str = "run",
@@ -192,6 +218,7 @@ def execute_and_report(
192
218
  tracer_fallback: bool | None = None,
193
219
  block_tags: list[str] | None = None,
194
220
  add_tags: list[str] | None = None,
221
+ wandb_to_trackio: bool = False,
195
222
  ) -> ExecutionReport:
196
223
  """Execute command via selected backend and show the run report."""
197
224
  hash_algos = cast(list[Literal["blake3", "sha256", "sha512", "md5"]], hash_algorithms)
@@ -214,6 +241,7 @@ def execute_and_report(
214
241
  tracer_fallback=tracer_fallback,
215
242
  block_tags=block_tags or [],
216
243
  add_tags=add_tags or [],
244
+ wandb_to_trackio=wandb_to_trackio,
217
245
  )
218
246
 
219
247
  backend = get_execution_backend(backend_name)
@@ -19,6 +19,7 @@ class RunRequest:
19
19
  hash_algorithms: tuple[str, ...] = field(default_factory=tuple)
20
20
  block_tags: tuple[str, ...] = field(default_factory=tuple)
21
21
  add_tags: tuple[str, ...] = field(default_factory=tuple)
22
+ wandb_to_trackio: bool = False
22
23
 
23
24
 
24
25
  @dataclass(frozen=True)
@@ -17,6 +17,7 @@ from .execution import (
17
17
  execute_and_report,
18
18
  get_hash_algorithms,
19
19
  validate_git_clean,
20
+ write_run_report_file,
20
21
  )
21
22
  from .requests import BuildRequest, RunRequest
22
23
  from .verbosity import resolve_verbosity
@@ -63,6 +64,7 @@ def run_command(request: RunRequest) -> int:
63
64
  tracer_fallback=request.tracer_fallback,
64
65
  block_tags=list(request.block_tags),
65
66
  add_tags=list(request.add_tags),
67
+ wandb_to_trackio=request.wandb_to_trackio,
66
68
  )
67
69
 
68
70
 
@@ -111,6 +113,7 @@ def _execute_tracked_command(
111
113
  tracer_fallback: bool | None,
112
114
  block_tags: list[str] | None = None,
113
115
  add_tags: list[str] | None = None,
116
+ wandb_to_trackio: bool = False,
114
117
  ) -> int:
115
118
  resolved_config_start_dir = config_start_dir or _config_start_dir(roar_dir)
116
119
  try:
@@ -138,6 +141,7 @@ def _execute_tracked_command(
138
141
  tracer_fallback=tracer_fallback,
139
142
  block_tags=block_tags,
140
143
  add_tags=add_tags,
144
+ wandb_to_trackio=wandb_to_trackio,
141
145
  )
142
146
  )
143
147
  except Exception:
@@ -150,6 +154,10 @@ def _execute_tracked_command(
150
154
  )
151
155
  raise
152
156
 
157
+ # Written before finalizers so a late finalizer crash cannot leave a
158
+ # wrapper believing the workload never launched.
159
+ write_run_report_file(report)
160
+
153
161
  try:
154
162
  if planned.finalize_run:
155
163
  planned.finalize_run(cast(Any, _FinalizerContext(roar_dir=roar_dir)))
@@ -176,6 +176,10 @@ def _populate_run_build_common_labels(roar: dict[str, Any], metadata: dict[str,
176
176
  row.get(key),
177
177
  )
178
178
 
179
+ # Per-run GPU-usage fingerprint from NVIDIA accounting mode. Only
180
+ # present when accounting was enabled; land it alongside cuda/gpu.
181
+ _copy_scalar_map(runtime.get("gpu_accounting"), roar, ["runtime", "gpu_accounting"])
182
+
179
183
  packages = metadata.get("packages")
180
184
  if isinstance(packages, dict):
181
185
  for manager, package_map in packages.items():
@@ -570,20 +570,26 @@ def parse_add_tags(pairs: Iterable[str]) -> dict[str, list[str]]:
570
570
 
571
571
 
572
572
  def build_run_modifiers(
573
- block_tags: Iterable[str], add_tags: Iterable[str]
574
- ) -> dict[str, list[str]] | None:
573
+ block_tags: Iterable[str],
574
+ add_tags: Iterable[str],
575
+ wandb_to_trackio: bool = False,
576
+ ) -> dict[str, Any] | None:
575
577
  """Build the ``run_modifiers`` metadata block, or None if there's nothing to record.
576
578
 
577
579
  Stores the raw flag strings verbatim (e.g. ``"license=GPL-3.0"``) so reproduce
578
- replays exactly what was passed.
580
+ replays exactly what was passed. ``wandb_to_trackio`` records that the run used
581
+ ``roar run --wandb-to-trackio`` so reproduce re-emits the flag (and the
582
+ reproduction's ``import wandb`` resolves the same way the original run's did).
579
583
  """
580
584
  blocks = [b.strip() for b in block_tags if b.strip()]
581
585
  adds = [a.strip() for a in add_tags if a.strip()]
582
- modifiers: dict[str, list[str]] = {}
586
+ modifiers: dict[str, Any] = {}
583
587
  if blocks:
584
588
  modifiers["block_tags"] = blocks
585
589
  if adds:
586
590
  modifiers["add_tags"] = adds
591
+ if wandb_to_trackio:
592
+ modifiers["wandb_to_trackio"] = True
587
593
  return modifiers or None
588
594
 
589
595
 
@@ -602,6 +608,8 @@ def run_modifier_flags(run_modifiers: Any) -> str:
602
608
  parts.append(f"--block-tag {shlex.quote(str(item))}")
603
609
  for item in run_modifiers.get("add_tags") or []:
604
610
  parts.append(f"--add-tag {shlex.quote(str(item))}")
611
+ if run_modifiers.get("wandb_to_trackio"):
612
+ parts.append("--wandb-to-trackio")
605
613
  return " ".join(parts)
606
614
 
607
615