roar-cli 0.3.5__tar.gz → 0.3.7__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 (438) hide show
  1. {roar_cli-0.3.5 → roar_cli-0.3.7}/LICENSE +2 -2
  2. {roar_cli-0.3.5 → roar_cli-0.3.7}/PKG-INFO +1 -1
  3. {roar_cli-0.3.5 → roar_cli-0.3.7}/pyproject.toml +1 -1
  4. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/git.py +41 -1
  5. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/labels.py +223 -9
  6. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/lookup/remote_artifacts.py +24 -0
  7. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/publish/git_remote.py +6 -1
  8. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/publish/register_execution.py +22 -2
  9. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/publish/register_tag_push.py +16 -0
  10. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/publish/registration_package.py +98 -18
  11. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/publish/results.py +10 -0
  12. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/publish/secrets.py +19 -0
  13. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/publish/service.py +71 -26
  14. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/query/__init__.py +12 -0
  15. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/query/inputs.py +122 -19
  16. roar_cli-0.3.7/roar/application/query/label.py +875 -0
  17. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/query/requests.py +40 -0
  18. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/query/results.py +10 -0
  19. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/query/show.py +108 -9
  20. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/query/status.py +84 -8
  21. roar_cli-0.3.7/roar/application/reproduce/environment.py +208 -0
  22. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/reproduce/lookup.py +65 -8
  23. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/reproduce/service.py +164 -12
  24. roar_cli-0.3.7/roar/application/reproducibility/report.py +315 -0
  25. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/run/execution.py +36 -3
  26. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/run/output_followup.py +47 -0
  27. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/run/service.py +17 -2
  28. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/run/verbosity.py +11 -15
  29. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/backends/osmo/host_execution.py +2 -2
  30. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/cli/command_registry.py +7 -0
  31. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/cli/commands/init.py +8 -10
  32. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/cli/commands/inputs.py +16 -0
  33. roar_cli-0.3.7/roar/cli/commands/label.py +320 -0
  34. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/cli/commands/put.py +48 -0
  35. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/cli/commands/register.py +153 -20
  36. roar_cli-0.3.7/roar/cli/commands/session.py +32 -0
  37. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/cli/commands/show.py +33 -2
  38. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/cli/commands/status.py +15 -2
  39. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/cli/decorators.py +34 -24
  40. roar_cli-0.3.7/roar/cli/publish_intent.py +183 -0
  41. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/cli/templates/agents/SKILL.md.tmpl +21 -1
  42. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/cli/templates/agents/agents_section.md.tmpl +2 -1
  43. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/core/interfaces/reproduction.py +4 -0
  44. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/core/models/run.py +34 -0
  45. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/provenance/file_filter.py +13 -1
  46. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/provenance/service.py +49 -0
  47. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/recording/job_recording.py +2 -1
  48. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/reproduction/environment_setup.py +113 -19
  49. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/reproduction/pipeline_executor.py +5 -0
  50. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/runtime/backup.py +5 -1
  51. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/runtime/coordinator.py +7 -3
  52. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/runtime/resources.py +3 -1
  53. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/runtime/tracer.py +71 -35
  54. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/filters/omit.py +70 -4
  55. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/config/loader.py +18 -10
  56. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/config/raw.py +41 -10
  57. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/glaas/client.py +66 -1
  58. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/glaas/registration/artifact.py +18 -9
  59. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/glaas/transport.py +31 -0
  60. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/presenters/show_renderer.py +7 -0
  61. roar_cli-0.3.7/roar/tui/screens/__init__.py +0 -0
  62. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/utils/git_url.py +19 -0
  63. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/tracers/preload/src/main.rs +490 -2
  64. roar_cli-0.3.5/roar/application/query/label.py +0 -368
  65. roar_cli-0.3.5/roar/application/reproduce/environment.py +0 -91
  66. roar_cli-0.3.5/roar/cli/commands/label.py +0 -196
  67. roar_cli-0.3.5/roar/cli/publish_intent.py +0 -81
  68. {roar_cli-0.3.5 → roar_cli-0.3.7}/README.md +0 -0
  69. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/__init__.py +0 -0
  70. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/__main__.py +0 -0
  71. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/analyzers/__init__.py +0 -0
  72. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/analyzers/base.py +0 -0
  73. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/analyzers/experiment_trackers.py +0 -0
  74. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/__init__.py +0 -0
  75. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/composite/__init__.py +0 -0
  76. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/composite/canonical.py +0 -0
  77. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/composite/detect.py +0 -0
  78. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/composite/qualifying.py +0 -0
  79. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/get/__init__.py +0 -0
  80. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/get/requests.py +0 -0
  81. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/get/results.py +0 -0
  82. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/get/service.py +0 -0
  83. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/get/transfer.py +0 -0
  84. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/label_rendering.py +0 -0
  85. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/lookup/__init__.py +0 -0
  86. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/lookup/models.py +0 -0
  87. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/lookup/policy.py +0 -0
  88. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/lookup/refs.py +0 -0
  89. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/lookup/runner.py +0 -0
  90. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/publish/__init__.py +0 -0
  91. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/publish/anchor_attribution.py +0 -0
  92. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/publish/blake3_upgrade.py +0 -0
  93. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/publish/collection.py +0 -0
  94. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/publish/composite_builder.py +0 -0
  95. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/publish/composites.py +0 -0
  96. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/publish/datasets.py +0 -0
  97. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/publish/form_composites.py +0 -0
  98. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/publish/job_links.py +0 -0
  99. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/publish/job_preparation.py +0 -0
  100. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/publish/lineage.py +0 -0
  101. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/publish/lineage_composite_formation.py +0 -0
  102. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/publish/lineage_composites.py +0 -0
  103. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/publish/metadata.py +0 -0
  104. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/publish/put_composites.py +0 -0
  105. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/publish/put_execution.py +0 -0
  106. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/publish/put_preparation.py +0 -0
  107. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/publish/register_preparation.py +0 -0
  108. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/publish/register_preview_jobs.py +0 -0
  109. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/publish/registration.py +0 -0
  110. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/publish/remote_job_uids.py +0 -0
  111. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/publish/remote_registry.py +0 -0
  112. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/publish/requests.py +0 -0
  113. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/publish/runtime.py +0 -0
  114. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/publish/session.py +0 -0
  115. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/publish/source_resolution.py +0 -0
  116. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/publish/targets.py +0 -0
  117. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/publish/view_edges.py +0 -0
  118. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/query/dag.py +0 -0
  119. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/query/db_status.py +0 -0
  120. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/query/diff.py +0 -0
  121. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/query/diff_engine.py +0 -0
  122. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/query/diff_graph.py +0 -0
  123. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/query/diff_refs.py +0 -0
  124. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/query/git_readiness.py +0 -0
  125. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/query/lineage.py +0 -0
  126. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/query/log.py +0 -0
  127. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/reproduce/__init__.py +0 -0
  128. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/reproduce/requests.py +0 -0
  129. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/reproduce/results.py +0 -0
  130. {roar_cli-0.3.5/roar/tui/screens → roar_cli-0.3.7/roar/application/reproducibility}/__init__.py +0 -0
  131. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/run/__init__.py +0 -0
  132. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/run/dag_references.py +0 -0
  133. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/run/dirty_tree_classify.py +0 -0
  134. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/run/dirty_tree_error.py +0 -0
  135. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/run/gitignore_suggest.py +0 -0
  136. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/run/requests.py +0 -0
  137. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/system_labels.py +0 -0
  138. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/workflow/__init__.py +0 -0
  139. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/workflow/requests.py +0 -0
  140. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/workflow/results.py +0 -0
  141. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/application/workflow/service.py +0 -0
  142. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/auth_store.py +0 -0
  143. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/backends/__init__.py +0 -0
  144. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/backends/local/__init__.py +0 -0
  145. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/backends/local/plugin.py +0 -0
  146. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/backends/osmo/__init__.py +0 -0
  147. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/backends/osmo/config.py +0 -0
  148. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/backends/osmo/export.py +0 -0
  149. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/backends/osmo/lineage.py +0 -0
  150. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/backends/osmo/plugin.py +0 -0
  151. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/backends/osmo/runtime_bundle.py +0 -0
  152. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/backends/osmo/submit.py +0 -0
  153. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/backends/osmo/workflow.py +0 -0
  154. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/backends/ray/__init__.py +0 -0
  155. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/backends/ray/_agent_names.py +0 -0
  156. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/backends/ray/collector.py +0 -0
  157. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/backends/ray/config.py +0 -0
  158. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/backends/ray/constants.py +0 -0
  159. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/backends/ray/env_contract.py +0 -0
  160. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/backends/ray/fragment.py +0 -0
  161. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/backends/ray/fragment_reconstituter.py +0 -0
  162. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/backends/ray/node_agent.py +0 -0
  163. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/backends/ray/plugin.py +0 -0
  164. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/backends/ray/proxy_fragments.py +0 -0
  165. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/backends/ray/roar_worker.py +0 -0
  166. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/backends/ray/runtime_hooks.py +0 -0
  167. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/backends/ray/s3_key_paths.py +0 -0
  168. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/backends/ray/submit.py +0 -0
  169. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/backends/ray/submit_context.py +0 -0
  170. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/cli/__init__.py +0 -0
  171. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/cli/_format.py +0 -0
  172. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/cli/commands/__init__.py +0 -0
  173. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/cli/commands/auth.py +0 -0
  174. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/cli/commands/build.py +0 -0
  175. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/cli/commands/config.py +0 -0
  176. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/cli/commands/dag.py +0 -0
  177. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/cli/commands/db.py +0 -0
  178. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/cli/commands/diff.py +0 -0
  179. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/cli/commands/env.py +0 -0
  180. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/cli/commands/export_registration_package.py +0 -0
  181. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/cli/commands/filter.py +0 -0
  182. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/cli/commands/get.py +0 -0
  183. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/cli/commands/init_agents.py +0 -0
  184. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/cli/commands/lineage.py +0 -0
  185. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/cli/commands/log.py +0 -0
  186. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/cli/commands/login.py +0 -0
  187. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/cli/commands/logout.py +0 -0
  188. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/cli/commands/osmo.py +0 -0
  189. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/cli/commands/pop.py +0 -0
  190. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/cli/commands/projects.py +0 -0
  191. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/cli/commands/proxy.py +0 -0
  192. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/cli/commands/reproduce.py +0 -0
  193. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/cli/commands/reset.py +0 -0
  194. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/cli/commands/run.py +0 -0
  195. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/cli/commands/scope.py +0 -0
  196. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/cli/commands/telemetry.py +0 -0
  197. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/cli/commands/tracer.py +0 -0
  198. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/cli/commands/tui.py +0 -0
  199. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/cli/commands/whoami.py +0 -0
  200. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/cli/commands/workflow.py +0 -0
  201. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/cli/context.py +0 -0
  202. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/core/__init__.py +0 -0
  203. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/core/bootstrap.py +0 -0
  204. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/core/canonical_session.py +0 -0
  205. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/core/digests.py +0 -0
  206. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/core/dto/__init__.py +0 -0
  207. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/core/dto/registration.py +0 -0
  208. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/core/exceptions.py +0 -0
  209. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/core/interfaces/__init__.py +0 -0
  210. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/core/interfaces/config.py +0 -0
  211. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/core/interfaces/lineage.py +0 -0
  212. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/core/interfaces/logger.py +0 -0
  213. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/core/interfaces/presenter.py +0 -0
  214. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/core/interfaces/provenance.py +0 -0
  215. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/core/interfaces/registration.py +0 -0
  216. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/core/interfaces/repositories.py +0 -0
  217. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/core/interfaces/run.py +0 -0
  218. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/core/interfaces/services.py +0 -0
  219. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/core/interfaces/telemetry.py +0 -0
  220. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/core/interfaces/vcs.py +0 -0
  221. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/core/label_constants.py +0 -0
  222. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/core/label_origins.py +0 -0
  223. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/core/logging.py +0 -0
  224. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/core/models/__init__.py +0 -0
  225. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/core/models/artifact.py +0 -0
  226. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/core/models/base.py +0 -0
  227. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/core/models/dag.py +0 -0
  228. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/core/models/dataset_identifier.py +0 -0
  229. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/core/models/glaas.py +0 -0
  230. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/core/models/job.py +0 -0
  231. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/core/models/lineage.py +0 -0
  232. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/core/models/provenance.py +0 -0
  233. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/core/models/session.py +0 -0
  234. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/core/models/telemetry.py +0 -0
  235. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/core/models/vcs.py +0 -0
  236. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/core/operation_metadata.py +0 -0
  237. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/core/session_hash.py +0 -0
  238. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/core/step_name.py +0 -0
  239. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/core/tracer_modes.py +0 -0
  240. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/core/validation.py +0 -0
  241. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/db/__init__.py +0 -0
  242. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/db/context.py +0 -0
  243. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/db/engine.py +0 -0
  244. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/db/hashing/__init__.py +0 -0
  245. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/db/hashing/backend.py +0 -0
  246. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/db/hashing/blake3.py +0 -0
  247. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/db/models.py +0 -0
  248. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/db/query_context.py +0 -0
  249. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/db/repositories/__init__.py +0 -0
  250. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/db/repositories/artifact.py +0 -0
  251. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/db/repositories/collection.py +0 -0
  252. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/db/repositories/composite.py +0 -0
  253. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/db/repositories/hash_cache.py +0 -0
  254. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/db/repositories/job.py +0 -0
  255. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/db/repositories/label.py +0 -0
  256. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/db/repositories/session.py +0 -0
  257. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/db/schema.py +0 -0
  258. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/db/services/__init__.py +0 -0
  259. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/db/services/hashing.py +0 -0
  260. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/db/services/job_recording.py +0 -0
  261. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/db/services/lineage.py +0 -0
  262. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/db/services/session.py +0 -0
  263. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/db/step_priority.py +0 -0
  264. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/__init__.py +0 -0
  265. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/cluster/__init__.py +0 -0
  266. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/cluster/bridge.py +0 -0
  267. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/cluster/proxy.py +0 -0
  268. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/cluster/proxy_config.py +0 -0
  269. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/fragments/__init__.py +0 -0
  270. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/fragments/lineage.py +0 -0
  271. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/fragments/models.py +0 -0
  272. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/fragments/reconstitution.py +0 -0
  273. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/fragments/sessions.py +0 -0
  274. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/fragments/transport.py +0 -0
  275. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/framework/__init__.py +0 -0
  276. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/framework/contract.py +0 -0
  277. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/framework/planning.py +0 -0
  278. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/framework/registry.py +0 -0
  279. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/framework/runtime_imports.py +0 -0
  280. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/provenance/__init__.py +0 -0
  281. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/provenance/assembler.py +0 -0
  282. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/provenance/build_pip_collector.py +0 -0
  283. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/provenance/build_tool_collector.py +0 -0
  284. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/provenance/data_loader.py +0 -0
  285. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/provenance/package_collector.py +0 -0
  286. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/provenance/process_summarizer.py +0 -0
  287. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/provenance/runtime_collector.py +0 -0
  288. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/recording/__init__.py +0 -0
  289. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/recording/dataset_identifier.py +0 -0
  290. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/recording/dataset_metadata.py +0 -0
  291. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/recording/dataset_profile.py +0 -0
  292. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/reproduction/__init__.py +0 -0
  293. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/reproduction/installers.py +0 -0
  294. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/reproduction/pipeline_metadata.py +0 -0
  295. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/runtime/__init__.py +0 -0
  296. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/runtime/abi_probe.py +0 -0
  297. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/runtime/driver_entrypoint.py +0 -0
  298. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/runtime/errors.py +0 -0
  299. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/runtime/host_execution.py +0 -0
  300. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/runtime/inject/__init__.py +0 -0
  301. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/runtime/inject/sitecustomize.py +0 -0
  302. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/runtime/inject/support.py +0 -0
  303. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/runtime/inject/tracker.py +0 -0
  304. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/runtime/lazy_install.py +0 -0
  305. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/runtime/proxy_resource.py +0 -0
  306. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/runtime/signal_handler.py +0 -0
  307. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/runtime/tracer_backends.py +0 -0
  308. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/runtime/tracer_banner.py +0 -0
  309. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/execution/runtime/worker_bootstrap.py +0 -0
  310. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/filters/__init__.py +0 -0
  311. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/filters/files.py +0 -0
  312. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/glaas_auth.py +0 -0
  313. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/glaas_client.py +0 -0
  314. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/__init__.py +0 -0
  315. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/bootstrap.py +0 -0
  316. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/config/__init__.py +0 -0
  317. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/config/access.py +0 -0
  318. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/config/schema.py +0 -0
  319. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/discovery.py +0 -0
  320. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/download/__init__.py +0 -0
  321. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/download/base.py +0 -0
  322. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/download/gcs.py +0 -0
  323. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/download/get.py +0 -0
  324. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/download/hf.py +0 -0
  325. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/download/http.py +0 -0
  326. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/download/noop.py +0 -0
  327. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/download/s3.py +0 -0
  328. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/git/__init__.py +0 -0
  329. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/git/base.py +0 -0
  330. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/git/context.py +0 -0
  331. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/git/provider.py +0 -0
  332. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/glaas/__init__.py +0 -0
  333. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/glaas/auth.py +0 -0
  334. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/glaas/fragment_streamer.py +0 -0
  335. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/glaas/registration/__init__.py +0 -0
  336. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/glaas/registration/_artifact_ref.py +0 -0
  337. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/glaas/registration/coordinator.py +0 -0
  338. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/glaas/registration/job.py +0 -0
  339. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/glaas/registration/session.py +0 -0
  340. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/registry.py +0 -0
  341. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/resolution.py +0 -0
  342. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/storage/__init__.py +0 -0
  343. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/storage/base.py +0 -0
  344. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/storage/gcs.py +0 -0
  345. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/storage/memory.py +0 -0
  346. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/storage/noop.py +0 -0
  347. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/storage/publish.py +0 -0
  348. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/storage/s3.py +0 -0
  349. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/telemetry/__init__.py +0 -0
  350. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/telemetry/base.py +0 -0
  351. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/integrations/telemetry/wandb.py +0 -0
  352. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/presenters/__init__.py +0 -0
  353. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/presenters/console.py +0 -0
  354. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/presenters/dag_data_builder.py +0 -0
  355. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/presenters/dag_renderer.py +0 -0
  356. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/presenters/diff_renderer.py +0 -0
  357. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/presenters/formatting.py +0 -0
  358. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/presenters/null.py +0 -0
  359. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/presenters/run_report.py +0 -0
  360. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/presenters/spinner.py +0 -0
  361. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/presenters/terminal.py +0 -0
  362. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/publish_auth.py +0 -0
  363. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/require.py +0 -0
  364. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/scope_config.py +0 -0
  365. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/telemetry/__init__.py +0 -0
  366. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/telemetry/_io.py +0 -0
  367. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/telemetry/capabilities.py +0 -0
  368. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/telemetry/config.py +0 -0
  369. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/telemetry/hooks.py +0 -0
  370. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/telemetry/install.py +0 -0
  371. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/telemetry/paths.py +0 -0
  372. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/telemetry/payload.py +0 -0
  373. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/telemetry/queue.py +0 -0
  374. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/telemetry/stats.py +0 -0
  375. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/telemetry/uploader.py +0 -0
  376. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/tui/__init__.py +0 -0
  377. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/tui/app.py +0 -0
  378. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/tui/data.py +0 -0
  379. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/tui/screens/config_editor.py +0 -0
  380. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/tui/screens/label_editor.py +0 -0
  381. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/tui/screens/launcher.py +0 -0
  382. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/tui/screens/log.py +0 -0
  383. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/tui/screens/main.py +0 -0
  384. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/tui/screens/search.py +0 -0
  385. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/tui/screens/session_picker.py +0 -0
  386. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/tui/tmux.py +0 -0
  387. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/tui/widgets/__init__.py +0 -0
  388. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/tui/widgets/detail.py +0 -0
  389. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/utils/__init__.py +0 -0
  390. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/utils/cloud.py +0 -0
  391. {roar_cli-0.3.5 → roar_cli-0.3.7}/roar/version_check.py +0 -0
  392. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/Cargo.lock +0 -0
  393. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/Cargo.toml +0 -0
  394. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/crates/artifact-hash-core/Cargo.toml +0 -0
  395. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/crates/artifact-hash-core/src/lib.rs +0 -0
  396. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/crates/artifact-hash-py/Cargo.toml +0 -0
  397. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/crates/artifact-hash-py/src/lib.rs +0 -0
  398. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/crates/tracer-fd/Cargo.toml +0 -0
  399. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/crates/tracer-fd/src/lib.rs +0 -0
  400. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/crates/tracer-runtime/Cargo.toml +0 -0
  401. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/crates/tracer-runtime/src/lib.rs +0 -0
  402. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/crates/tracer-schema/Cargo.toml +0 -0
  403. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/crates/tracer-schema/src/lib.rs +0 -0
  404. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/services/proxy/Cargo.lock +0 -0
  405. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/services/proxy/Cargo.toml +0 -0
  406. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/services/proxy/src/forward.rs +0 -0
  407. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/services/proxy/src/main.rs +0 -0
  408. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/services/proxy/src/s3.rs +0 -0
  409. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/tracers/ebpf/common/Cargo.toml +0 -0
  410. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/tracers/ebpf/common/src/lib.rs +0 -0
  411. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/tracers/ebpf/probe/Cargo.toml +0 -0
  412. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/tracers/ebpf/probe/rust-toolchain.toml +0 -0
  413. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/tracers/ebpf/probe/src/main.rs +0 -0
  414. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/tracers/ebpf/userspace/Cargo.toml +0 -0
  415. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/tracers/ebpf/userspace/build.rs +0 -0
  416. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/tracers/ebpf/userspace/src/attach.rs +0 -0
  417. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/tracers/ebpf/userspace/src/bin/roard.rs +0 -0
  418. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/tracers/ebpf/userspace/src/client.rs +0 -0
  419. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/tracers/ebpf/userspace/src/daemon.rs +0 -0
  420. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/tracers/ebpf/userspace/src/events.rs +0 -0
  421. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/tracers/ebpf/userspace/src/ipc.rs +0 -0
  422. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/tracers/ebpf/userspace/src/lib.rs +0 -0
  423. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/tracers/ebpf/userspace/src/main.rs +0 -0
  424. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/tracers/ebpf/userspace/src/state.rs +0 -0
  425. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/tracers/preload/Cargo.toml +0 -0
  426. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/tracers/preload/build.rs +0 -0
  427. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/tracers/preload/src/bin/io_fixture.rs +0 -0
  428. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/tracers/preload/src/interpose.c +0 -0
  429. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/tracers/preload/src/ipc.rs +0 -0
  430. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/tracers/preload/src/lib.rs +0 -0
  431. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/tracers/preload/tests/comprehensive.rs +0 -0
  432. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/tracers/preload/tests/standalone.rs +0 -0
  433. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/tracers/ptrace/Cargo.toml +0 -0
  434. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/tracers/ptrace/rustfmt.toml +0 -0
  435. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/tracers/ptrace/src/arch.rs +0 -0
  436. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/tracers/ptrace/src/main.rs +0 -0
  437. {roar_cli-0.3.5 → roar_cli-0.3.7}/rust/tracers/ptrace/src/seccomp.rs +0 -0
  438. {roar_cli-0.3.5 → roar_cli-0.3.7}/scripts/sync_packaged_rust_artifacts.py +0 -0
@@ -187,7 +187,7 @@
187
187
  same "printed page" as the copyright notice for easier
188
188
  identification within third-party archives.
189
189
 
190
- Copyright [yyyy] [name of copyright owner]
190
+ Copyright [2026] [TReqs Inc]
191
191
 
192
192
  Licensed under the Apache License, Version 2.0 (the "License");
193
193
  you may not use this file except in compliance with the License.
@@ -199,4 +199,4 @@
199
199
  distributed under the License is distributed on an "AS IS" BASIS,
200
200
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
201
  See the License for the specific language governing permissions and
202
- limitations under the License.
202
+ limitations under the License.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: roar-cli
3
- Version: 0.3.5
3
+ Version: 0.3.7
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.3.5"
8
+ version = "0.3.7"
9
9
  description = "Reproducibility and provenance tracker for ML training pipelines"
10
10
  authors = [
11
11
  { name="TReqs Team", email="info@treqs.ai" }
@@ -3,12 +3,13 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import subprocess
6
- from dataclasses import dataclass
6
+ from dataclasses import dataclass, replace
7
7
  from pathlib import Path
8
8
 
9
9
  from ..core.interfaces.logger import ILogger
10
10
  from ..core.interfaces.registration import GitContext
11
11
  from ..integrations.git import GitVCSProvider, resolve_git_context
12
+ from ..utils.git_url import is_shareable_remote
12
13
 
13
14
 
14
15
  @dataclass(frozen=True)
@@ -68,6 +69,29 @@ def resolve_roar_git_context(
68
69
  """
69
70
  logger.debug("Resolving git context from %s", path)
70
71
  ctx = resolve_git_context(path, git_commit, configured_remote=configured_remote)
72
+ # A repo with no real remote records its own ``file://`` path as the URL.
73
+ # That resolves only on this machine, so publishing it both leaks the
74
+ # user's local filesystem layout to GLaaS and is useless to anyone else.
75
+ # This resolver is publish-only (register/put/package prep), so drop the
76
+ # non-shareable URL here — the publish record then honestly shows "no
77
+ # remote", matching the reproducibility checklist. (Local recording uses
78
+ # ``resolve_git_context`` directly and keeps the ``file://`` URI, which
79
+ # in-place reproduce relies on.)
80
+ if ctx.repo and not is_shareable_remote(ctx.repo):
81
+ logger.debug("Dropping non-shareable git repo URL from publish context: %s", ctx.repo)
82
+ ctx = replace(ctx, repo=None)
83
+ # A remote URL can embed credentials (https://user:token@host,
84
+ # https://TOKEN@host, ssh://user:pass@host). Redact them here, at the
85
+ # publish-side source, so every publish flow (register, put, package
86
+ # export) and the canonical session hash see the same credential-free
87
+ # URL — downstream send paths filter again as defense in depth.
88
+ if ctx.repo:
89
+ redacted_repo = _redact_publish_repo_url(ctx.repo, path)
90
+ if redacted_repo != ctx.repo:
91
+ logger.warning(
92
+ "Redacted credentials from git repo URL before publish: %s", redacted_repo
93
+ )
94
+ ctx = replace(ctx, repo=redacted_repo)
71
95
  logger.debug(
72
96
  "Git context resolved: repo=%s, commit=%s, branch=%s",
73
97
  ctx.repo,
@@ -77,6 +101,22 @@ def resolve_roar_git_context(
77
101
  return ctx
78
102
 
79
103
 
104
+ def _redact_publish_repo_url(repo_url: str, start_dir: Path) -> str:
105
+ """Redact embedded credentials from a publish-bound git repo URL.
106
+
107
+ Honors the same ``registration.omit`` config (enabled flag, allowlist,
108
+ custom patterns) as the registration payload filters.
109
+ """
110
+ from ..filters.omit import OmitFilter
111
+ from ..integrations.config.raw import get_raw_registration_omit_config
112
+
113
+ omit_config = get_raw_registration_omit_config(start_dir=str(start_dir))
114
+ if not omit_config.get("enabled", True):
115
+ return repo_url
116
+ filtered, _detections = OmitFilter(omit_config).filter_git_url(repo_url)
117
+ return filtered
118
+
119
+
80
120
  def build_roar_git_tag_name(commit: str, *, short: bool = False) -> str:
81
121
  """Build the canonical roar git tag name."""
82
122
  normalized_commit = commit[:8] if short else commit
@@ -42,6 +42,27 @@ class LabelWriteResult:
42
42
  version: int | None = None
43
43
 
44
44
 
45
+ @dataclass(frozen=True)
46
+ class ReconcileTargetSync:
47
+ """Correlates one outbound label-reconcile payload item to the local label
48
+ row(s) it came from and the deletion keys (if any) requested for it.
49
+
50
+ A single ``roar label sync`` call can push several targets (dag, jobs,
51
+ artifacts) in one reconcile request. This lets the caller match each
52
+ target's entry in the GLaaS response back to the local rows that should
53
+ (or, if a requested deletion wasn't confirmed, should NOT) get their
54
+ ``synced_at`` baseline advanced. See
55
+ ``roar/application/query/label.py::_mark_labels_synced_confirming_deletions``.
56
+ """
57
+
58
+ entity_type: str
59
+ session_hash: str | None
60
+ job_uid: str | None
61
+ artifact_hash: str | None
62
+ label_ids: list[int]
63
+ deleted_keys: list[str]
64
+
65
+
45
66
  class _LabelSyncDatabaseContext(Protocol):
46
67
  @property
47
68
  def labels(self) -> Any: ...
@@ -512,6 +533,156 @@ def collect_label_sync_payloads(
512
533
  return payloads
513
534
 
514
535
 
536
+ def _user_label_key_paths(metadata: Any) -> set[str]:
537
+ if not isinstance(metadata, dict):
538
+ return set()
539
+ return {key for key, _value in flatten_label_metadata(strip_reserved_system_labels(metadata))}
540
+
541
+
542
+ def deleted_user_label_keys(
543
+ db_ctx: _LabelSyncDatabaseContext,
544
+ *,
545
+ entity_type: str,
546
+ session_id: int | None = None,
547
+ job_id: int | None = None,
548
+ artifact_id: str | None = None,
549
+ ) -> list[str]:
550
+ """User-label key paths removed locally since the last synced version.
551
+
552
+ The newest version stamped ``synced_at`` is the remote baseline: keys
553
+ present there but absent from the current version were deliberately unset
554
+ locally and should be deleted remotely on the next reconcile.
555
+ """
556
+ history = db_ctx.labels.get_history(
557
+ entity_type,
558
+ session_id=session_id,
559
+ job_id=job_id,
560
+ artifact_id=artifact_id,
561
+ )
562
+ synced = [row for row in history if row.get("synced_at") is not None]
563
+ if not history or not synced:
564
+ return []
565
+ baseline = max(synced, key=lambda row: int(row.get("version") or 0))
566
+ current = max(history, key=lambda row: int(row.get("version") or 0))
567
+ if int(baseline.get("version") or 0) >= int(current.get("version") or 0):
568
+ return []
569
+ baseline_keys = _user_label_key_paths(baseline.get("metadata"))
570
+ current_keys = _user_label_key_paths(current.get("metadata"))
571
+ return sorted(baseline_keys - current_keys)
572
+
573
+
574
+ def _current_label_row_id(
575
+ db_ctx: _LabelSyncDatabaseContext,
576
+ *,
577
+ entity_type: str,
578
+ session_id: int | None = None,
579
+ job_id: int | None = None,
580
+ artifact_id: str | None = None,
581
+ ) -> int | None:
582
+ """Local row id of the current label version for a target, if any."""
583
+ current = db_ctx.labels.get_current(
584
+ entity_type,
585
+ session_id=session_id,
586
+ job_id=job_id,
587
+ artifact_id=artifact_id,
588
+ )
589
+ if isinstance(current, dict) and isinstance(current.get("id"), int):
590
+ return int(current["id"])
591
+ return None
592
+
593
+
594
+ def _attach_deleted_user_keys_for_lineage(
595
+ db_ctx: _LabelSyncDatabaseContext,
596
+ payloads: list[dict[str, Any]],
597
+ *,
598
+ session_id: int | None,
599
+ jobs: list[dict[str, Any]],
600
+ artifacts: list[dict[str, Any]],
601
+ ) -> None:
602
+ """Stamp locally-unset user keys and the source label row id onto reconcile
603
+ payloads, per target.
604
+
605
+ ``_label_row_id`` is transient bookkeeping consumed by ``_split_label_row_ids``
606
+ below (it is never sent to GLaaS) so the caller can correlate the server's
607
+ response back to the local row(s) that should have ``synced_at`` advanced.
608
+ """
609
+ job_id_by_uid: dict[str, int] = {}
610
+ for job in jobs:
611
+ job_id = job.get("id")
612
+ job_uid = job.get("job_uid")
613
+ remote_job_uid = job.get("remote_job_uid")
614
+ resolved = remote_job_uid if isinstance(remote_job_uid, str) and remote_job_uid else job_uid
615
+ if isinstance(job_id, int) and isinstance(resolved, str) and resolved:
616
+ job_id_by_uid.setdefault(resolved, job_id)
617
+
618
+ artifact_id_by_hash: dict[str, str] = {}
619
+ for artifact in artifacts:
620
+ artifact_id = artifact.get("id")
621
+ artifact_hash = artifact.get("hash")
622
+ if isinstance(artifact_id, str) and isinstance(artifact_hash, str) and artifact_hash:
623
+ artifact_id_by_hash.setdefault(artifact_hash, artifact_id)
624
+
625
+ for payload in payloads:
626
+ entity_type = payload.get("entity_type")
627
+ deleted: list[str] = []
628
+ label_id: int | None = None
629
+ if entity_type == "dag" and session_id is not None:
630
+ deleted = deleted_user_label_keys(db_ctx, entity_type="dag", session_id=session_id)
631
+ label_id = _current_label_row_id(db_ctx, entity_type="dag", session_id=session_id)
632
+ elif entity_type == "job":
633
+ job_id = job_id_by_uid.get(str(payload.get("job_uid") or ""))
634
+ if job_id is not None:
635
+ deleted = deleted_user_label_keys(db_ctx, entity_type="job", job_id=job_id)
636
+ label_id = _current_label_row_id(db_ctx, entity_type="job", job_id=job_id)
637
+ elif entity_type == "artifact":
638
+ artifact_id = artifact_id_by_hash.get(str(payload.get("artifact_hash") or ""))
639
+ if artifact_id is not None:
640
+ deleted = deleted_user_label_keys(
641
+ db_ctx,
642
+ entity_type="artifact",
643
+ artifact_id=artifact_id,
644
+ )
645
+ label_id = _current_label_row_id(
646
+ db_ctx, entity_type="artifact", artifact_id=artifact_id
647
+ )
648
+ if deleted:
649
+ payload["deleted_keys"] = deleted
650
+ if label_id is not None:
651
+ payload["_label_row_id"] = label_id
652
+
653
+
654
+ def _split_label_row_ids(
655
+ payloads: list[dict[str, Any]],
656
+ ) -> tuple[list[dict[str, Any]], list[ReconcileTargetSync]]:
657
+ """Strip the transient ``_label_row_id`` key from outbound wire payloads.
658
+
659
+ Returns the cleaned payloads (safe to JSON-serialize to GLaaS) alongside a
660
+ parallel, same-order list of ``ReconcileTargetSync`` records so the caller
661
+ can verify server-confirmed deletions before advancing each target's local
662
+ ``synced_at`` baseline.
663
+ """
664
+ wire_payloads: list[dict[str, Any]] = []
665
+ targets: list[ReconcileTargetSync] = []
666
+ for payload in payloads:
667
+ label_row_id = payload.get("_label_row_id")
668
+ wire_payloads.append({k: v for k, v in payload.items() if k != "_label_row_id"})
669
+ deleted_keys = payload.get("deleted_keys")
670
+ session_hash = payload.get("session_hash")
671
+ job_uid = payload.get("job_uid")
672
+ artifact_hash = payload.get("artifact_hash")
673
+ targets.append(
674
+ ReconcileTargetSync(
675
+ entity_type=str(payload.get("entity_type") or ""),
676
+ session_hash=session_hash if isinstance(session_hash, str) else None,
677
+ job_uid=job_uid if isinstance(job_uid, str) else None,
678
+ artifact_hash=artifact_hash if isinstance(artifact_hash, str) else None,
679
+ label_ids=[int(label_row_id)] if isinstance(label_row_id, int) else [],
680
+ deleted_keys=list(deleted_keys) if isinstance(deleted_keys, list) else [],
681
+ )
682
+ )
683
+ return wire_payloads, targets
684
+
685
+
515
686
  def collect_current_label_ids(
516
687
  db_ctx: _LabelSyncDatabaseContext,
517
688
  *,
@@ -576,8 +747,15 @@ def build_reconcile_payload_for_current_lineage(
576
747
  db_ctx: _RemoteLabelMutationDatabaseContext,
577
748
  *,
578
749
  roar_dir: Path,
579
- ) -> tuple[str, list[dict[str, Any]]]:
580
- """Build a user-managed reconcile payload for the active local lineage."""
750
+ ) -> tuple[str, list[dict[str, Any]], list[ReconcileTargetSync]]:
751
+ """Build a user-managed reconcile payload for the active local lineage.
752
+
753
+ Returns the published session hash, the reconcile label payloads (including
754
+ per-target ``deleted_keys`` for locally-unset user labels), and a per-target
755
+ ``ReconcileTargetSync`` list (same order as the payloads) the caller uses to
756
+ decide which local label rows may have ``synced_at`` stamped after a push —
757
+ see ``roar/application/query/label.py::_mark_labels_synced_confirming_deletions``.
758
+ """
581
759
  session = db_ctx.sessions.get_active()
582
760
  if not isinstance(session, dict) or not isinstance(session.get("id"), int):
583
761
  raise ValueError("No active session.")
@@ -594,14 +772,23 @@ def build_reconcile_payload_for_current_lineage(
594
772
  list(getattr(lineage, "jobs", []) or []),
595
773
  session,
596
774
  )
775
+ artifacts = list(getattr(lineage, "artifacts", []) or [])
597
776
  payloads = collect_label_sync_payloads(
598
777
  db_ctx,
599
778
  session_id=session_id,
600
779
  session_hash=session_hash,
601
780
  jobs=jobs,
602
- artifacts=list(getattr(lineage, "artifacts", []) or []),
781
+ artifacts=artifacts,
782
+ )
783
+ _attach_deleted_user_keys_for_lineage(
784
+ db_ctx,
785
+ payloads,
786
+ session_id=session_id,
787
+ jobs=jobs,
788
+ artifacts=artifacts,
603
789
  )
604
- return session_hash, _user_managed_reconcile_payloads(payloads)
790
+ wire_payloads, sync_targets = _split_label_row_ids(_user_managed_reconcile_payloads(payloads))
791
+ return session_hash, wire_payloads, sync_targets
605
792
 
606
793
 
607
794
  def build_reconcile_payload_for_target(
@@ -610,8 +797,12 @@ def build_reconcile_payload_for_target(
610
797
  roar_dir: Path,
611
798
  target: LabelTargetRef,
612
799
  metadata: dict[str, Any],
613
- ) -> tuple[str, list[dict[str, Any]]]:
614
- """Build a single-target user-managed reconcile payload."""
800
+ ) -> tuple[str, list[dict[str, Any]], list[ReconcileTargetSync]]:
801
+ """Build a single-target user-managed reconcile payload.
802
+
803
+ See ``build_reconcile_payload_for_current_lineage`` for what the returned
804
+ ``ReconcileTargetSync`` list is used for.
805
+ """
615
806
  payload = build_remote_label_mutation_payload(
616
807
  db_ctx,
617
808
  roar_dir=roar_dir,
@@ -619,6 +810,15 @@ def build_reconcile_payload_for_target(
619
810
  metadata=metadata,
620
811
  require_published_session=True,
621
812
  )
813
+ deleted = deleted_user_label_keys(
814
+ db_ctx,
815
+ entity_type=target.entity_type,
816
+ session_id=target.session_id,
817
+ job_id=target.job_id,
818
+ artifact_id=target.artifact_id,
819
+ )
820
+ if deleted:
821
+ payload["deleted_keys"] = deleted
622
822
  session_hash = payload.get("session_hash")
623
823
  if not isinstance(session_hash, str) or not session_hash:
624
824
  session_hash = _canonical_remote_session_hash_for_target(
@@ -627,7 +827,17 @@ def build_reconcile_payload_for_target(
627
827
  target=target,
628
828
  require_published=True,
629
829
  )
630
- return session_hash, _user_managed_reconcile_payloads([payload])
830
+ label_id = _current_label_row_id(
831
+ db_ctx,
832
+ entity_type=target.entity_type,
833
+ session_id=target.session_id,
834
+ job_id=target.job_id,
835
+ artifact_id=target.artifact_id,
836
+ )
837
+ if label_id is not None:
838
+ payload["_label_row_id"] = label_id
839
+ wire_payloads, sync_targets = _split_label_row_ids(_user_managed_reconcile_payloads([payload]))
840
+ return session_hash, wire_payloads, sync_targets
631
841
 
632
842
 
633
843
  def _canonical_remote_session_hash(
@@ -730,14 +940,18 @@ def _user_managed_reconcile_payloads(payloads: list[dict[str, Any]]) -> list[dic
730
940
  if not isinstance(metadata, dict):
731
941
  continue
732
942
  user_metadata = _prune_empty_containers(strip_reserved_system_labels(metadata))
733
- if not user_metadata:
943
+ deleted_keys = payload.get("deleted_keys")
944
+ has_deletions = isinstance(deleted_keys, list) and bool(deleted_keys)
945
+ # A target whose user labels were all unset still needs a reconcile item
946
+ # so the deletions propagate remotely.
947
+ if not user_metadata and not has_deletions:
734
948
  continue
735
949
  filtered.append(
736
950
  {
737
951
  key: value
738
952
  for key, value in {
739
953
  **payload,
740
- "metadata": user_metadata,
954
+ "metadata": user_metadata if isinstance(user_metadata, dict) else {},
741
955
  }.items()
742
956
  if key != "key_origins"
743
957
  }
@@ -22,12 +22,36 @@ def lookup_remote_artifact(
22
22
  ) -> tuple[dict[str, Any] | None, str | None]:
23
23
  """Resolve a remote artifact by hash prefix.
24
24
 
25
+ Tries the authenticated lookup first. If that's rejected for lack of
26
+ credentials (401/403) — the common case for a user with no SSH key
27
+ registered looking up a public artifact — falls back to the public,
28
+ optionally-authenticated endpoint so anonymous reads still work.
29
+
25
30
  Returns ``(artifact, error_message)``. A 404 is treated as a clean miss.
26
31
  """
27
32
  reader = artifact_reader or GlaasClient(base_url=server_url)
28
33
 
29
34
  try:
30
35
  artifact = reader.get_artifact(hash_prefix)
36
+ except GlaasApiError as exc:
37
+ if exc.status_code == 404:
38
+ return None, None
39
+ if exc.status_code in (401, 403) and hasattr(reader, "get_public_artifact"):
40
+ return _lookup_public_artifact(reader, hash_prefix)
41
+ return None, str(exc)
42
+ except (ValueError, RuntimeError) as exc:
43
+ return None, str(exc)
44
+
45
+ if not isinstance(artifact, dict):
46
+ return None, None
47
+ return artifact, None
48
+
49
+
50
+ def _lookup_public_artifact(
51
+ reader: SupportsArtifactLookup, hash_prefix: str
52
+ ) -> tuple[dict[str, Any] | None, str | None]:
53
+ try:
54
+ artifact = reader.get_public_artifact(hash_prefix) # type: ignore[attr-defined]
31
55
  except GlaasApiError as exc:
32
56
  if exc.status_code == 404:
33
57
  return None, None
@@ -60,7 +60,8 @@ def _git_check_output(repo_root: Path | str, *args: str, capture_stderr: bool) -
60
60
  )
61
61
 
62
62
 
63
- def _list_remote_names(repo_root: Path | str) -> list[str]:
63
+ def list_remote_names(repo_root: Path | str) -> list[str]:
64
+ """Return the names of git remotes configured in this repo (empty if none)."""
64
65
  try:
65
66
  raw = _git_check_output(repo_root, "remote", capture_stderr=False)
66
67
  except subprocess.CalledProcessError:
@@ -68,6 +69,10 @@ def _list_remote_names(repo_root: Path | str) -> list[str]:
68
69
  return [line.strip() for line in raw.splitlines() if line.strip()]
69
70
 
70
71
 
72
+ # Back-compat alias for internal callers.
73
+ _list_remote_names = list_remote_names
74
+
75
+
71
76
  def resolve_canonical_remote(repo_root: Path | str, configured_remote: str | None) -> str:
72
77
  """Return the name of the remote roar should push tags to.
73
78
 
@@ -24,7 +24,11 @@ from .job_preparation import (
24
24
  order_jobs_for_registration,
25
25
  )
26
26
  from .remote_job_uids import prepare_jobs_for_remote_publication
27
- from .secrets import detect_lineage_secrets, filter_lineage_secrets
27
+ from .secrets import (
28
+ detect_lineage_secrets,
29
+ filter_git_context_secrets,
30
+ filter_lineage_secrets,
31
+ )
28
32
  from .session import build_staged_lineage_counts
29
33
 
30
34
  if TYPE_CHECKING:
@@ -265,6 +269,12 @@ class RegisterService:
265
269
  lineage=lineage,
266
270
  omit_filter=omit_filter,
267
271
  )
272
+ # The git repo URL is published at the session level (register /
273
+ # finalize), so it must be redacted here too, not just detected.
274
+ git_context, _ = filter_git_context_secrets(
275
+ git_context=git_context,
276
+ omit_filter=omit_filter,
277
+ )
268
278
 
269
279
  registration_jobs = order_jobs_for_registration(
270
280
  normalize_jobs_for_registration(lineage.jobs)
@@ -469,8 +479,18 @@ class RegisterService:
469
479
 
470
480
  composite_registered = sum(1 for item in composite_registrations if item.get("registered"))
471
481
  composite_failed = sum(1 for item in composite_registrations if not item.get("registered"))
472
- total_artifacts_registered = batch_result.artifacts_registered + composite_registered
473
482
  total_artifacts_failed = batch_result.artifacts_failed + composite_failed
483
+ # Report DISTINCT artifacts, matching `register --dry-run`'s
484
+ # len(lineage.artifacts). The coordinator's running tally double-counts
485
+ # (artifacts are tallied in both the staging and the link phase, and the
486
+ # server's success count is per content-hash) — when everything
487
+ # registered, the distinct figure is simply the lineage's artifact count.
488
+ # The success gate below keys off *_failed, not this display number, so
489
+ # this is safe. On partial failure, fall back to the coordinator's tally.
490
+ if total_artifacts_failed == 0:
491
+ total_artifacts_registered = len(lineage.artifacts)
492
+ else:
493
+ total_artifacts_registered = batch_result.artifacts_registered + composite_registered
474
494
 
475
495
  success = (
476
496
  batch_result.jobs_failed == 0 and total_artifacts_failed == 0 and not finalize_failed
@@ -33,6 +33,7 @@ from ...core.interfaces.logger import ILogger
33
33
  from ..git import build_roar_git_tag_name, create_roar_git_tag
34
34
  from .git_remote import (
35
35
  GitRemoteError,
36
+ list_remote_names,
36
37
  push_roar_tags,
37
38
  resolve_canonical_remote,
38
39
  warn_if_ssh_passphrase_prompt_likely,
@@ -145,6 +146,21 @@ def ensure_roar_tags_pushed(
145
146
  push_skipped_reason="never_config",
146
147
  )
147
148
 
149
+ # No remote at all (and none configured): degrade to a local-only register
150
+ # instead of blocking. The common "does this work" loop shouldn't be gated on
151
+ # having a remote — and the dry-run never blocks, so the real run shouldn't
152
+ # contradict it. Tags exist locally; the reproducibility checklist surfaces
153
+ # that the commit isn't reachable on a remote. (An *invalid* configured
154
+ # remote or ambiguous multi-remote setup still errors below — those mean the
155
+ # user wants a push but roar can't safely pick where.)
156
+ if not configured_remote and not list_remote_names(repo_root):
157
+ logger.debug("No git remote configured — registering local-only (tags not pushed).")
158
+ return RegisterTagSummary(
159
+ session_tag=session_tag_name,
160
+ job_tags=job_tags,
161
+ push_skipped_reason="no_remote",
162
+ )
163
+
148
164
  try:
149
165
  remote = resolve_canonical_remote(repo_root, configured_remote)
150
166
  except GitRemoteError as exc: