roar-cli 0.3.5__tar.gz → 0.3.6__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 (434) hide show
  1. {roar_cli-0.3.5 → roar_cli-0.3.6}/PKG-INFO +1 -1
  2. {roar_cli-0.3.5 → roar_cli-0.3.6}/pyproject.toml +1 -1
  3. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/git.py +13 -1
  4. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/publish/git_remote.py +6 -1
  5. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/publish/register_execution.py +11 -1
  6. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/publish/register_tag_push.py +16 -0
  7. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/publish/registration_package.py +24 -0
  8. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/publish/results.py +10 -0
  9. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/publish/service.py +71 -26
  10. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/query/inputs.py +122 -19
  11. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/query/requests.py +2 -0
  12. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/query/results.py +4 -0
  13. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/query/status.py +53 -0
  14. roar_cli-0.3.6/roar/application/reproduce/environment.py +208 -0
  15. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/reproduce/lookup.py +65 -8
  16. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/reproduce/service.py +164 -12
  17. roar_cli-0.3.6/roar/application/reproducibility/report.py +315 -0
  18. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/run/execution.py +22 -1
  19. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/run/output_followup.py +47 -0
  20. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/commands/init.py +8 -10
  21. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/commands/inputs.py +16 -0
  22. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/commands/put.py +48 -0
  23. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/commands/register.py +115 -18
  24. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/commands/status.py +15 -2
  25. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/publish_intent.py +47 -7
  26. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/templates/agents/SKILL.md.tmpl +21 -1
  27. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/templates/agents/agents_section.md.tmpl +2 -1
  28. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/core/interfaces/reproduction.py +4 -0
  29. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/provenance/file_filter.py +13 -1
  30. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/provenance/service.py +49 -0
  31. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/reproduction/environment_setup.py +113 -19
  32. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/reproduction/pipeline_executor.py +5 -0
  33. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/runtime/coordinator.py +1 -0
  34. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/runtime/tracer.py +32 -20
  35. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/glaas/registration/artifact.py +18 -9
  36. roar_cli-0.3.6/roar/tui/screens/__init__.py +0 -0
  37. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/utils/git_url.py +19 -0
  38. roar_cli-0.3.5/roar/application/reproduce/environment.py +0 -91
  39. {roar_cli-0.3.5 → roar_cli-0.3.6}/LICENSE +0 -0
  40. {roar_cli-0.3.5 → roar_cli-0.3.6}/README.md +0 -0
  41. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/__init__.py +0 -0
  42. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/__main__.py +0 -0
  43. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/analyzers/__init__.py +0 -0
  44. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/analyzers/base.py +0 -0
  45. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/analyzers/experiment_trackers.py +0 -0
  46. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/__init__.py +0 -0
  47. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/composite/__init__.py +0 -0
  48. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/composite/canonical.py +0 -0
  49. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/composite/detect.py +0 -0
  50. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/composite/qualifying.py +0 -0
  51. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/get/__init__.py +0 -0
  52. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/get/requests.py +0 -0
  53. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/get/results.py +0 -0
  54. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/get/service.py +0 -0
  55. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/get/transfer.py +0 -0
  56. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/label_rendering.py +0 -0
  57. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/labels.py +0 -0
  58. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/lookup/__init__.py +0 -0
  59. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/lookup/models.py +0 -0
  60. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/lookup/policy.py +0 -0
  61. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/lookup/refs.py +0 -0
  62. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/lookup/remote_artifacts.py +0 -0
  63. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/lookup/runner.py +0 -0
  64. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/publish/__init__.py +0 -0
  65. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/publish/anchor_attribution.py +0 -0
  66. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/publish/blake3_upgrade.py +0 -0
  67. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/publish/collection.py +0 -0
  68. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/publish/composite_builder.py +0 -0
  69. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/publish/composites.py +0 -0
  70. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/publish/datasets.py +0 -0
  71. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/publish/form_composites.py +0 -0
  72. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/publish/job_links.py +0 -0
  73. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/publish/job_preparation.py +0 -0
  74. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/publish/lineage.py +0 -0
  75. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/publish/lineage_composite_formation.py +0 -0
  76. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/publish/lineage_composites.py +0 -0
  77. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/publish/metadata.py +0 -0
  78. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/publish/put_composites.py +0 -0
  79. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/publish/put_execution.py +0 -0
  80. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/publish/put_preparation.py +0 -0
  81. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/publish/register_preparation.py +0 -0
  82. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/publish/register_preview_jobs.py +0 -0
  83. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/publish/registration.py +0 -0
  84. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/publish/remote_job_uids.py +0 -0
  85. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/publish/remote_registry.py +0 -0
  86. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/publish/requests.py +0 -0
  87. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/publish/runtime.py +0 -0
  88. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/publish/secrets.py +0 -0
  89. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/publish/session.py +0 -0
  90. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/publish/source_resolution.py +0 -0
  91. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/publish/targets.py +0 -0
  92. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/publish/view_edges.py +0 -0
  93. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/query/__init__.py +0 -0
  94. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/query/dag.py +0 -0
  95. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/query/db_status.py +0 -0
  96. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/query/diff.py +0 -0
  97. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/query/diff_engine.py +0 -0
  98. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/query/diff_graph.py +0 -0
  99. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/query/diff_refs.py +0 -0
  100. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/query/git_readiness.py +0 -0
  101. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/query/label.py +0 -0
  102. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/query/lineage.py +0 -0
  103. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/query/log.py +0 -0
  104. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/query/show.py +0 -0
  105. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/reproduce/__init__.py +0 -0
  106. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/reproduce/requests.py +0 -0
  107. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/reproduce/results.py +0 -0
  108. {roar_cli-0.3.5/roar/tui/screens → roar_cli-0.3.6/roar/application/reproducibility}/__init__.py +0 -0
  109. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/run/__init__.py +0 -0
  110. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/run/dag_references.py +0 -0
  111. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/run/dirty_tree_classify.py +0 -0
  112. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/run/dirty_tree_error.py +0 -0
  113. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/run/gitignore_suggest.py +0 -0
  114. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/run/requests.py +0 -0
  115. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/run/service.py +0 -0
  116. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/run/verbosity.py +0 -0
  117. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/system_labels.py +0 -0
  118. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/workflow/__init__.py +0 -0
  119. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/workflow/requests.py +0 -0
  120. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/workflow/results.py +0 -0
  121. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/application/workflow/service.py +0 -0
  122. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/auth_store.py +0 -0
  123. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/backends/__init__.py +0 -0
  124. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/backends/local/__init__.py +0 -0
  125. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/backends/local/plugin.py +0 -0
  126. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/backends/osmo/__init__.py +0 -0
  127. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/backends/osmo/config.py +0 -0
  128. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/backends/osmo/export.py +0 -0
  129. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/backends/osmo/host_execution.py +0 -0
  130. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/backends/osmo/lineage.py +0 -0
  131. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/backends/osmo/plugin.py +0 -0
  132. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/backends/osmo/runtime_bundle.py +0 -0
  133. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/backends/osmo/submit.py +0 -0
  134. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/backends/osmo/workflow.py +0 -0
  135. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/backends/ray/__init__.py +0 -0
  136. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/backends/ray/_agent_names.py +0 -0
  137. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/backends/ray/collector.py +0 -0
  138. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/backends/ray/config.py +0 -0
  139. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/backends/ray/constants.py +0 -0
  140. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/backends/ray/env_contract.py +0 -0
  141. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/backends/ray/fragment.py +0 -0
  142. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/backends/ray/fragment_reconstituter.py +0 -0
  143. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/backends/ray/node_agent.py +0 -0
  144. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/backends/ray/plugin.py +0 -0
  145. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/backends/ray/proxy_fragments.py +0 -0
  146. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/backends/ray/roar_worker.py +0 -0
  147. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/backends/ray/runtime_hooks.py +0 -0
  148. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/backends/ray/s3_key_paths.py +0 -0
  149. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/backends/ray/submit.py +0 -0
  150. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/backends/ray/submit_context.py +0 -0
  151. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/__init__.py +0 -0
  152. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/_format.py +0 -0
  153. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/command_registry.py +0 -0
  154. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/commands/__init__.py +0 -0
  155. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/commands/auth.py +0 -0
  156. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/commands/build.py +0 -0
  157. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/commands/config.py +0 -0
  158. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/commands/dag.py +0 -0
  159. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/commands/db.py +0 -0
  160. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/commands/diff.py +0 -0
  161. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/commands/env.py +0 -0
  162. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/commands/export_registration_package.py +0 -0
  163. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/commands/filter.py +0 -0
  164. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/commands/get.py +0 -0
  165. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/commands/init_agents.py +0 -0
  166. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/commands/label.py +0 -0
  167. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/commands/lineage.py +0 -0
  168. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/commands/log.py +0 -0
  169. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/commands/login.py +0 -0
  170. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/commands/logout.py +0 -0
  171. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/commands/osmo.py +0 -0
  172. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/commands/pop.py +0 -0
  173. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/commands/projects.py +0 -0
  174. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/commands/proxy.py +0 -0
  175. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/commands/reproduce.py +0 -0
  176. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/commands/reset.py +0 -0
  177. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/commands/run.py +0 -0
  178. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/commands/scope.py +0 -0
  179. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/commands/show.py +0 -0
  180. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/commands/telemetry.py +0 -0
  181. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/commands/tracer.py +0 -0
  182. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/commands/tui.py +0 -0
  183. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/commands/whoami.py +0 -0
  184. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/commands/workflow.py +0 -0
  185. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/context.py +0 -0
  186. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/cli/decorators.py +0 -0
  187. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/core/__init__.py +0 -0
  188. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/core/bootstrap.py +0 -0
  189. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/core/canonical_session.py +0 -0
  190. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/core/digests.py +0 -0
  191. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/core/dto/__init__.py +0 -0
  192. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/core/dto/registration.py +0 -0
  193. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/core/exceptions.py +0 -0
  194. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/core/interfaces/__init__.py +0 -0
  195. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/core/interfaces/config.py +0 -0
  196. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/core/interfaces/lineage.py +0 -0
  197. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/core/interfaces/logger.py +0 -0
  198. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/core/interfaces/presenter.py +0 -0
  199. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/core/interfaces/provenance.py +0 -0
  200. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/core/interfaces/registration.py +0 -0
  201. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/core/interfaces/repositories.py +0 -0
  202. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/core/interfaces/run.py +0 -0
  203. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/core/interfaces/services.py +0 -0
  204. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/core/interfaces/telemetry.py +0 -0
  205. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/core/interfaces/vcs.py +0 -0
  206. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/core/label_constants.py +0 -0
  207. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/core/label_origins.py +0 -0
  208. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/core/logging.py +0 -0
  209. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/core/models/__init__.py +0 -0
  210. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/core/models/artifact.py +0 -0
  211. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/core/models/base.py +0 -0
  212. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/core/models/dag.py +0 -0
  213. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/core/models/dataset_identifier.py +0 -0
  214. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/core/models/glaas.py +0 -0
  215. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/core/models/job.py +0 -0
  216. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/core/models/lineage.py +0 -0
  217. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/core/models/provenance.py +0 -0
  218. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/core/models/run.py +0 -0
  219. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/core/models/session.py +0 -0
  220. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/core/models/telemetry.py +0 -0
  221. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/core/models/vcs.py +0 -0
  222. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/core/operation_metadata.py +0 -0
  223. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/core/session_hash.py +0 -0
  224. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/core/step_name.py +0 -0
  225. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/core/tracer_modes.py +0 -0
  226. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/core/validation.py +0 -0
  227. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/db/__init__.py +0 -0
  228. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/db/context.py +0 -0
  229. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/db/engine.py +0 -0
  230. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/db/hashing/__init__.py +0 -0
  231. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/db/hashing/backend.py +0 -0
  232. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/db/hashing/blake3.py +0 -0
  233. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/db/models.py +0 -0
  234. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/db/query_context.py +0 -0
  235. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/db/repositories/__init__.py +0 -0
  236. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/db/repositories/artifact.py +0 -0
  237. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/db/repositories/collection.py +0 -0
  238. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/db/repositories/composite.py +0 -0
  239. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/db/repositories/hash_cache.py +0 -0
  240. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/db/repositories/job.py +0 -0
  241. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/db/repositories/label.py +0 -0
  242. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/db/repositories/session.py +0 -0
  243. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/db/schema.py +0 -0
  244. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/db/services/__init__.py +0 -0
  245. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/db/services/hashing.py +0 -0
  246. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/db/services/job_recording.py +0 -0
  247. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/db/services/lineage.py +0 -0
  248. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/db/services/session.py +0 -0
  249. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/db/step_priority.py +0 -0
  250. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/__init__.py +0 -0
  251. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/cluster/__init__.py +0 -0
  252. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/cluster/bridge.py +0 -0
  253. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/cluster/proxy.py +0 -0
  254. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/cluster/proxy_config.py +0 -0
  255. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/fragments/__init__.py +0 -0
  256. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/fragments/lineage.py +0 -0
  257. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/fragments/models.py +0 -0
  258. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/fragments/reconstitution.py +0 -0
  259. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/fragments/sessions.py +0 -0
  260. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/fragments/transport.py +0 -0
  261. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/framework/__init__.py +0 -0
  262. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/framework/contract.py +0 -0
  263. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/framework/planning.py +0 -0
  264. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/framework/registry.py +0 -0
  265. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/framework/runtime_imports.py +0 -0
  266. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/provenance/__init__.py +0 -0
  267. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/provenance/assembler.py +0 -0
  268. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/provenance/build_pip_collector.py +0 -0
  269. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/provenance/build_tool_collector.py +0 -0
  270. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/provenance/data_loader.py +0 -0
  271. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/provenance/package_collector.py +0 -0
  272. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/provenance/process_summarizer.py +0 -0
  273. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/provenance/runtime_collector.py +0 -0
  274. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/recording/__init__.py +0 -0
  275. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/recording/dataset_identifier.py +0 -0
  276. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/recording/dataset_metadata.py +0 -0
  277. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/recording/dataset_profile.py +0 -0
  278. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/recording/job_recording.py +0 -0
  279. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/reproduction/__init__.py +0 -0
  280. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/reproduction/installers.py +0 -0
  281. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/reproduction/pipeline_metadata.py +0 -0
  282. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/runtime/__init__.py +0 -0
  283. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/runtime/abi_probe.py +0 -0
  284. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/runtime/backup.py +0 -0
  285. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/runtime/driver_entrypoint.py +0 -0
  286. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/runtime/errors.py +0 -0
  287. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/runtime/host_execution.py +0 -0
  288. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/runtime/inject/__init__.py +0 -0
  289. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/runtime/inject/sitecustomize.py +0 -0
  290. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/runtime/inject/support.py +0 -0
  291. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/runtime/inject/tracker.py +0 -0
  292. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/runtime/lazy_install.py +0 -0
  293. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/runtime/proxy_resource.py +0 -0
  294. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/runtime/resources.py +0 -0
  295. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/runtime/signal_handler.py +0 -0
  296. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/runtime/tracer_backends.py +0 -0
  297. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/runtime/tracer_banner.py +0 -0
  298. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/execution/runtime/worker_bootstrap.py +0 -0
  299. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/filters/__init__.py +0 -0
  300. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/filters/files.py +0 -0
  301. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/filters/omit.py +0 -0
  302. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/glaas_auth.py +0 -0
  303. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/glaas_client.py +0 -0
  304. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/__init__.py +0 -0
  305. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/bootstrap.py +0 -0
  306. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/config/__init__.py +0 -0
  307. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/config/access.py +0 -0
  308. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/config/loader.py +0 -0
  309. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/config/raw.py +0 -0
  310. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/config/schema.py +0 -0
  311. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/discovery.py +0 -0
  312. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/download/__init__.py +0 -0
  313. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/download/base.py +0 -0
  314. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/download/gcs.py +0 -0
  315. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/download/get.py +0 -0
  316. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/download/hf.py +0 -0
  317. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/download/http.py +0 -0
  318. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/download/noop.py +0 -0
  319. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/download/s3.py +0 -0
  320. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/git/__init__.py +0 -0
  321. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/git/base.py +0 -0
  322. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/git/context.py +0 -0
  323. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/git/provider.py +0 -0
  324. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/glaas/__init__.py +0 -0
  325. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/glaas/auth.py +0 -0
  326. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/glaas/client.py +0 -0
  327. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/glaas/fragment_streamer.py +0 -0
  328. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/glaas/registration/__init__.py +0 -0
  329. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/glaas/registration/_artifact_ref.py +0 -0
  330. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/glaas/registration/coordinator.py +0 -0
  331. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/glaas/registration/job.py +0 -0
  332. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/glaas/registration/session.py +0 -0
  333. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/glaas/transport.py +0 -0
  334. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/registry.py +0 -0
  335. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/resolution.py +0 -0
  336. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/storage/__init__.py +0 -0
  337. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/storage/base.py +0 -0
  338. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/storage/gcs.py +0 -0
  339. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/storage/memory.py +0 -0
  340. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/storage/noop.py +0 -0
  341. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/storage/publish.py +0 -0
  342. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/storage/s3.py +0 -0
  343. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/telemetry/__init__.py +0 -0
  344. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/telemetry/base.py +0 -0
  345. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/integrations/telemetry/wandb.py +0 -0
  346. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/presenters/__init__.py +0 -0
  347. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/presenters/console.py +0 -0
  348. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/presenters/dag_data_builder.py +0 -0
  349. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/presenters/dag_renderer.py +0 -0
  350. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/presenters/diff_renderer.py +0 -0
  351. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/presenters/formatting.py +0 -0
  352. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/presenters/null.py +0 -0
  353. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/presenters/run_report.py +0 -0
  354. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/presenters/show_renderer.py +0 -0
  355. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/presenters/spinner.py +0 -0
  356. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/presenters/terminal.py +0 -0
  357. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/publish_auth.py +0 -0
  358. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/require.py +0 -0
  359. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/scope_config.py +0 -0
  360. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/telemetry/__init__.py +0 -0
  361. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/telemetry/_io.py +0 -0
  362. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/telemetry/capabilities.py +0 -0
  363. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/telemetry/config.py +0 -0
  364. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/telemetry/hooks.py +0 -0
  365. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/telemetry/install.py +0 -0
  366. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/telemetry/paths.py +0 -0
  367. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/telemetry/payload.py +0 -0
  368. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/telemetry/queue.py +0 -0
  369. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/telemetry/stats.py +0 -0
  370. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/telemetry/uploader.py +0 -0
  371. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/tui/__init__.py +0 -0
  372. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/tui/app.py +0 -0
  373. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/tui/data.py +0 -0
  374. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/tui/screens/config_editor.py +0 -0
  375. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/tui/screens/label_editor.py +0 -0
  376. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/tui/screens/launcher.py +0 -0
  377. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/tui/screens/log.py +0 -0
  378. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/tui/screens/main.py +0 -0
  379. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/tui/screens/search.py +0 -0
  380. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/tui/screens/session_picker.py +0 -0
  381. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/tui/tmux.py +0 -0
  382. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/tui/widgets/__init__.py +0 -0
  383. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/tui/widgets/detail.py +0 -0
  384. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/utils/__init__.py +0 -0
  385. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/utils/cloud.py +0 -0
  386. {roar_cli-0.3.5 → roar_cli-0.3.6}/roar/version_check.py +0 -0
  387. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/Cargo.lock +0 -0
  388. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/Cargo.toml +0 -0
  389. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/crates/artifact-hash-core/Cargo.toml +0 -0
  390. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/crates/artifact-hash-core/src/lib.rs +0 -0
  391. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/crates/artifact-hash-py/Cargo.toml +0 -0
  392. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/crates/artifact-hash-py/src/lib.rs +0 -0
  393. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/crates/tracer-fd/Cargo.toml +0 -0
  394. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/crates/tracer-fd/src/lib.rs +0 -0
  395. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/crates/tracer-runtime/Cargo.toml +0 -0
  396. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/crates/tracer-runtime/src/lib.rs +0 -0
  397. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/crates/tracer-schema/Cargo.toml +0 -0
  398. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/crates/tracer-schema/src/lib.rs +0 -0
  399. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/services/proxy/Cargo.lock +0 -0
  400. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/services/proxy/Cargo.toml +0 -0
  401. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/services/proxy/src/forward.rs +0 -0
  402. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/services/proxy/src/main.rs +0 -0
  403. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/services/proxy/src/s3.rs +0 -0
  404. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/tracers/ebpf/common/Cargo.toml +0 -0
  405. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/tracers/ebpf/common/src/lib.rs +0 -0
  406. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/tracers/ebpf/probe/Cargo.toml +0 -0
  407. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/tracers/ebpf/probe/rust-toolchain.toml +0 -0
  408. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/tracers/ebpf/probe/src/main.rs +0 -0
  409. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/tracers/ebpf/userspace/Cargo.toml +0 -0
  410. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/tracers/ebpf/userspace/build.rs +0 -0
  411. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/tracers/ebpf/userspace/src/attach.rs +0 -0
  412. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/tracers/ebpf/userspace/src/bin/roard.rs +0 -0
  413. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/tracers/ebpf/userspace/src/client.rs +0 -0
  414. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/tracers/ebpf/userspace/src/daemon.rs +0 -0
  415. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/tracers/ebpf/userspace/src/events.rs +0 -0
  416. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/tracers/ebpf/userspace/src/ipc.rs +0 -0
  417. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/tracers/ebpf/userspace/src/lib.rs +0 -0
  418. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/tracers/ebpf/userspace/src/main.rs +0 -0
  419. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/tracers/ebpf/userspace/src/state.rs +0 -0
  420. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/tracers/preload/Cargo.toml +0 -0
  421. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/tracers/preload/build.rs +0 -0
  422. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/tracers/preload/src/bin/io_fixture.rs +0 -0
  423. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/tracers/preload/src/interpose.c +0 -0
  424. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/tracers/preload/src/ipc.rs +0 -0
  425. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/tracers/preload/src/lib.rs +0 -0
  426. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/tracers/preload/src/main.rs +0 -0
  427. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/tracers/preload/tests/comprehensive.rs +0 -0
  428. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/tracers/preload/tests/standalone.rs +0 -0
  429. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/tracers/ptrace/Cargo.toml +0 -0
  430. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/tracers/ptrace/rustfmt.toml +0 -0
  431. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/tracers/ptrace/src/arch.rs +0 -0
  432. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/tracers/ptrace/src/main.rs +0 -0
  433. {roar_cli-0.3.5 → roar_cli-0.3.6}/rust/tracers/ptrace/src/seccomp.rs +0 -0
  434. {roar_cli-0.3.5 → roar_cli-0.3.6}/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.3.5
3
+ Version: 0.3.6
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.6"
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,17 @@ 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)
71
83
  logger.debug(
72
84
  "Git context resolved: repo=%s, commit=%s, branch=%s",
73
85
  ctx.repo,
@@ -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
 
@@ -469,8 +469,18 @@ class RegisterService:
469
469
 
470
470
  composite_registered = sum(1 for item in composite_registrations if item.get("registered"))
471
471
  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
472
  total_artifacts_failed = batch_result.artifacts_failed + composite_failed
473
+ # Report DISTINCT artifacts, matching `register --dry-run`'s
474
+ # len(lineage.artifacts). The coordinator's running tally double-counts
475
+ # (artifacts are tallied in both the staging and the link phase, and the
476
+ # server's success count is per content-hash) — when everything
477
+ # registered, the distinct figure is simply the lineage's artifact count.
478
+ # The success gate below keys off *_failed, not this display number, so
479
+ # this is safe. On partial failure, fall back to the coordinator's tally.
480
+ if total_artifacts_failed == 0:
481
+ total_artifacts_registered = len(lineage.artifacts)
482
+ else:
483
+ total_artifacts_registered = batch_result.artifacts_registered + composite_registered
474
484
 
475
485
  success = (
476
486
  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:
@@ -134,6 +134,9 @@ def build_registration_package(
134
134
  git_context=git_context,
135
135
  cwd=cwd,
136
136
  )
137
+ redacted_lineage, redacted_git_context = _drop_local_remotes(
138
+ redacted_lineage, redacted_git_context
139
+ )
137
140
 
138
141
  registration_jobs = order_jobs_for_registration(
139
142
  normalize_jobs_for_registration(redacted_lineage.jobs)
@@ -263,6 +266,27 @@ def _apply_redaction(
263
266
  )
264
267
 
265
268
 
269
+ def _drop_local_remotes(
270
+ lineage: LineageData, git_context: GitContext
271
+ ) -> tuple[LineageData, GitContext]:
272
+ """Don't publish non-shareable (``file://`` / local-path) git repos to GLaaS.
273
+
274
+ A repo with no real remote records its own ``file://`` path as ``git_repo``;
275
+ publishing that leaks the local filesystem path and is useless to anyone else.
276
+ Replace such repos with "" so the GLaaS record honestly shows no remote — the
277
+ reproducibility checklist already flags this as "commit reachable on a remote".
278
+ """
279
+ from ...utils.git_url import is_shareable_remote
280
+
281
+ if git_context.repo and not is_shareable_remote(git_context.repo):
282
+ git_context = GitContext(repo="", commit=git_context.commit, branch=git_context.branch)
283
+ for job in lineage.jobs:
284
+ repo = job.get("git_repo")
285
+ if isinstance(repo, str) and repo and not is_shareable_remote(repo):
286
+ job["git_repo"] = ""
287
+ return lineage, git_context
288
+
289
+
266
290
  def _filter_git_context(
267
291
  git_context: GitContext,
268
292
  omit_filter: OmitFilter | None,
@@ -49,6 +49,11 @@ class RegisterLineageResponse:
49
49
  # the CLI surfaces a notice so the user knows it can't be reproduced from
50
50
  # source. Defaults True so existing/normal registrations are unaffected.
51
51
  reproducible: bool = True
52
+ # False when the session's steps span more than one git commit (the user
53
+ # committed between runs). Computed from the session's commit span — the
54
+ # SAME source `roar reproduce` uses — so the two checklists never disagree.
55
+ # Defaults True so single-commit/normal registrations are unaffected.
56
+ single_commit: bool = True
52
57
 
53
58
 
54
59
  @dataclass(frozen=True)
@@ -94,3 +99,8 @@ class PutResponse:
94
99
  git_tag: str | None = None
95
100
  warnings: list[str] = field(default_factory=list)
96
101
  error: str | None = None
102
+ # Reproducibility-checklist inputs, mirroring RegisterLineageResponse so
103
+ # `roar put` can render the same receipt as `roar register`.
104
+ reproducible: bool = True # the published run has a git commit
105
+ single_commit: bool = True # the session's steps share one commit
106
+ commit_on_remote: bool = False # the commit is reachable on a shareable remote
@@ -370,13 +370,13 @@ def _resolve_register_preview_git_context(*, path: Path, logger: Any) -> Any:
370
370
  commit = _run_git(repo_root_path, "rev-parse", "HEAD")
371
371
  branch = _run_git(repo_root_path, "rev-parse", "--abbrev-ref", "HEAD")
372
372
  remote = _run_git(repo_root_path, "remote", "get-url", "origin")
373
- repo = remote or repo_root_path.resolve().as_uri()
373
+ # Publish-only preview: never record a local ``file://`` URI here. A repo
374
+ # with no shareable remote publishes as "no remote" (matching the real
375
+ # register path, which drops it in `resolve_roar_git_context`) rather than
376
+ # leaking the local filesystem path to GLaaS.
377
+ repo = remote if remote else None
374
378
  if remote is None:
375
- logger.debug(
376
- "No git remote configured for %s; using local repository URI %s",
377
- repo_root_path,
378
- repo,
379
- )
379
+ logger.debug("No git remote configured for %s; publishing with no remote", repo_root_path)
380
380
 
381
381
  return GitContext(repo=repo, commit=commit, branch=branch)
382
382
 
@@ -436,6 +436,31 @@ def _form_lineage_composites_for_lineage(*, roar_dir: Path, lineage: Any, logger
436
436
  return form_lineage_composites(db_ctx=form_db, job_ids=job_ids, logger=logger)
437
437
 
438
438
 
439
+ def _session_single_commit(*, roar_dir: Path, session_id: Any) -> bool:
440
+ """True iff the session's steps all ran at one git commit.
441
+
442
+ Computed from the session's commit span (``git_commit_start`` vs
443
+ ``git_commit_end``) — the SAME formula ``roar reproduce`` uses (see
444
+ ``reproduce/lookup.py``) — so register's receipt and reproduce's preview can
445
+ never disagree on the "single git commit" check. The old proxy (extra job
446
+ tags) read False-positive whenever tagging was skipped (e.g. no remote),
447
+ silently mis-scoring multi-commit lineages as single-commit. Best-effort:
448
+ defaults True (the existing assume-single behavior) on any miss.
449
+ """
450
+ if session_id is None:
451
+ return True
452
+ try:
453
+ with create_query_database_context(roar_dir) as db_ctx:
454
+ session = db_ctx.sessions.get(session_id)
455
+ except Exception:
456
+ return True
457
+ if not session:
458
+ return True
459
+ start = session.get("git_commit_start")
460
+ end = session.get("git_commit_end")
461
+ return not (start and end and start != end)
462
+
463
+
439
464
  def _load_remote_job_uid_mapping(*, roar_dir: Path, session_id: Any) -> dict[str, str]:
440
465
  """Return the ``{local_job_uid: remote_job_uid}`` map registration persisted.
441
466
 
@@ -593,6 +618,12 @@ def register_lineage_target(request: RegisterLineageRequest) -> RegisterLineageR
593
618
  except Exception as exc: # attribution is best-effort
594
619
  logger.debug("anchor attribution skipped: %s", exc)
595
620
 
621
+ # Did the lineage span more than one git commit? Compute it the same way
622
+ # `roar reproduce` does (commit span), so the two checklists agree.
623
+ single_commit = _session_single_commit(
624
+ roar_dir=request.roar_dir, session_id=collected_lineage.session_id
625
+ )
626
+
596
627
  # Collapse each job's dataset membership into consumes/produces view edges (a
597
628
  # bloom over the touched leaves) and prune the subsumed leaves from the bundle.
598
629
  # Pushed after the main registration. Best-effort.
@@ -637,7 +668,9 @@ def register_lineage_target(request: RegisterLineageRequest) -> RegisterLineageR
637
668
  )
638
669
 
639
670
  if request.dry_run:
640
- return preview_register_lineage(
671
+ from dataclasses import replace
672
+
673
+ preview = preview_register_lineage(
641
674
  lineage=collected_lineage.lineage,
642
675
  artifact_hash=collected_lineage.artifact_hash,
643
676
  prepared=prepared,
@@ -645,6 +678,7 @@ def register_lineage_target(request: RegisterLineageRequest) -> RegisterLineageR
645
678
  skip_confirmation=request.skip_confirmation,
646
679
  confirm_callback=request.confirm_callback,
647
680
  )
681
+ return replace(preview, single_commit=single_commit)
648
682
 
649
683
  # P1-23: push roar tags BEFORE writing the GLaaS record so the
650
684
  # record never references a tag that doesn't yet exist on the
@@ -743,33 +777,27 @@ def register_lineage_target(request: RegisterLineageRequest) -> RegisterLineageR
743
777
  tag_summary=tag_summary,
744
778
  warnings=warnings,
745
779
  reproducible=bool(prepared.git_context.commit),
780
+ single_commit=single_commit,
746
781
  )
747
782
  except PublishAuthError as exc:
748
783
  return RegisterLineageResponse(success=False, error=str(exc))
749
784
 
750
785
 
751
786
  def _format_anonymous_tag_push_warning(tag_push_error: str) -> str:
752
- """Wrap a tag-push failure as a self-contained user-facing warning.
753
-
754
- Anonymous register continues past the push failure (GLaaS publish
755
- succeeds), so the message has to (a) make clear the failure is git
756
- remote auth, not GLaaS, (b) tell the user GLaaS registration still
757
- happened, (c) explain why the missing push matters (the GLaaS
758
- record references a tag that doesn't yet exist on the remote, so
759
- anyone reading the record can't ``git checkout`` it), and
760
- (d) point at the real fix (configure git remote auth + push the
761
- tag). We deliberately do *not* suggest
762
- ``git.push_tags_on_register=never`` here — that "fix" breaks
763
- reproducibility for everyone viewing the GLaaS record, not just
764
- silences a local warning.
787
+ """One-line tag-push-failure warning for the anonymous register path.
788
+
789
+ Anonymous register continues past a push failure (GLaaS publish succeeds).
790
+ The "why a missing push matters" explanation now lives in the reproducibility
791
+ checklist's ``commit reachable on a remote`` item, so this stays terse: name
792
+ that the failure is git-remote auth (not GLaaS), that the record was still
793
+ registered, the fix, and the verbatim git error. (Deliberately not suggesting
794
+ ``git.push_tags_on_register=never`` that "fix" breaks reproducibility for
795
+ everyone reading the record, it doesn't just silence the warning.)
765
796
  """
766
797
  return (
767
- "roar tag push to git remote failed (git auth, not GLaaS) — "
768
- "anonymous register continued without pushing the tag.\n"
769
- " The local tag exists, but viewers of the GLaaS record need it "
770
- "on the remote to reproduce.\n"
771
- " Fix git remote auth, then push: `git push <remote> <tag>`.\n"
772
- f" Verbatim git error: {tag_push_error}"
798
+ "roar tag push to the git remote failed (git auth, not GLaaS) — registered "
799
+ "without it; the 'commit reachable on a remote' check flags this. "
800
+ f"Fix git remote auth and re-push (`git push <remote> <tag>`). git: {tag_push_error}"
773
801
  )
774
802
 
775
803
 
@@ -787,6 +815,9 @@ def put_artifacts(request: PutRequest) -> PutResponse:
787
815
  )
788
816
 
789
817
  repo_root = request.repo_root or request.cwd
818
+ # Reproducibility-checklist facts, filled in on the real (non-dry-run) path.
819
+ put_single_commit = True
820
+ put_commit_on_remote = False
790
821
  if request.dry_run:
791
822
  git_state = None
792
823
  git_commit = None
@@ -842,6 +873,17 @@ def put_artifacts(request: PutRequest) -> PutResponse:
842
873
  logger=logger,
843
874
  )
844
875
 
876
+ # Reproducibility facts for the receipt: same commit-span source as
877
+ # register/reproduce, and whether the commit is reachable on a real
878
+ # remote (git_context.repo is None here when no shareable remote —
879
+ # resolve_roar_git_context drops local file:// URIs).
880
+ from ...utils.git_url import is_shareable_remote
881
+
882
+ put_single_commit = _session_single_commit(
883
+ roar_dir=request.roar_dir, session_id=prepared.session_id
884
+ )
885
+ put_commit_on_remote = is_shareable_remote(prepared.git_context.repo)
886
+
845
887
  result = service.put_prepared(
846
888
  prepared=prepared,
847
889
  sources=request.sources,
@@ -886,6 +928,9 @@ def put_artifacts(request: PutRequest) -> PutResponse:
886
928
  git_tag=created_git_tag,
887
929
  warnings=warnings,
888
930
  error=result.error,
931
+ reproducible=bool(git_commit),
932
+ single_commit=put_single_commit,
933
+ commit_on_remote=put_commit_on_remote,
889
934
  )
890
935
 
891
936
 
@@ -4,6 +4,7 @@ from __future__ import annotations
4
4
 
5
5
  import json
6
6
  import os
7
+ import subprocess
7
8
  from pathlib import Path
8
9
  from typing import Any
9
10
 
@@ -29,16 +30,45 @@ def render_inputs(request: InputsQueryRequest) -> str:
29
30
  return summary.message
30
31
 
31
32
  lines: list[str] = []
33
+ any_unsourced = any(a.unsourced for a in summary.artifacts)
34
+ tmp_unsourced = sum(
35
+ 1 for a in summary.artifacts if a.unsourced and is_ephemeral_tmp_path(a.path)
36
+ )
32
37
  for art in summary.artifacts:
33
38
  digest = _short_digest(art.hashes)
34
39
  path = art.path or "(no path)"
35
- if digest:
36
- lines.append(f"{path} {digest}")
37
- else:
38
- lines.append(path)
40
+ marker = "⚠ " if art.unsourced else (" " if any_unsourced else "")
41
+ suffix = f" {digest}" if digest else ""
42
+ lines.append(f"{marker}{path}{suffix}")
43
+ if any_unsourced:
44
+ lines.append("")
45
+ lines.append(
46
+ "⚠ unsourced: nothing tracked produced this file, so it won't exist on another machine."
47
+ )
48
+ lines.append(
49
+ " Make it reproducible — commit code to a git repo, or ingest data with "
50
+ "`roar get <url>` / `roar run wget <url>`."
51
+ )
52
+ if tmp_unsourced:
53
+ lines.append(
54
+ f"⚠ {tmp_unsourced} in /tmp — these definitely won't survive; "
55
+ "move into your project or ingest with `roar get`."
56
+ )
39
57
  return "\n".join(lines)
40
58
 
41
59
 
60
+ def is_ephemeral_tmp_path(path: str | None) -> bool:
61
+ """True for an input under an ephemeral tmp dir (Linux /tmp, macOS var/folders).
62
+
63
+ Such a file is guaranteed not to exist when the lineage is reproduced on
64
+ another machine — a sharper, more certain failure than generic
65
+ unsourcedness, so it warrants its own escalated warning.
66
+ """
67
+ if not path:
68
+ return False
69
+ return path.startswith("/tmp/") or "/private/var/folders/" in path
70
+
71
+
42
72
  def _short_digest(hashes: list[ShowHashSummary]) -> str:
43
73
  """Return a short display digest like 'blake3:abcdef01...'."""
44
74
  for h in hashes:
@@ -67,14 +97,20 @@ def build_inputs_summary(request: InputsQueryRequest) -> InputsSummary:
67
97
  message=f'"{target_label}" is a root artifact (no upstream inputs)',
68
98
  )
69
99
 
100
+ git_tracked = _git_tracked_paths(request.cwd)
70
101
  if request.direct:
71
- artifacts = _get_direct_inputs(db_ctx, target_artifact_ids)
102
+ artifacts = _get_direct_inputs(db_ctx, target_artifact_ids, git_tracked)
72
103
  elif request.show_all:
73
104
  artifacts = _walk_upstream_all(
74
- db_ctx, target_artifact_ids, exclude=set(target_artifact_ids)
105
+ db_ctx, target_artifact_ids, git_tracked, exclude=set(target_artifact_ids)
75
106
  )
76
107
  else:
77
- artifacts = _walk_upstream_roots(db_ctx, target_artifact_ids)
108
+ artifacts = _walk_upstream_roots(db_ctx, target_artifact_ids, git_tracked)
109
+
110
+ if request.unsourced:
111
+ artifacts = [a for a in artifacts if a.unsourced]
112
+ elif request.sourced:
113
+ artifacts = [a for a in artifacts if not a.unsourced]
78
114
 
79
115
  return InputsSummary(
80
116
  target_ref=target_label,
@@ -201,7 +237,56 @@ def _is_root_artifact(db_ctx, artifact_id: str) -> bool:
201
237
  return len(inputs) == 0
202
238
 
203
239
 
204
- def _make_artifact_summary(artifact: dict[str, Any]) -> InputArtifactSummary:
240
+ def _git_tracked_paths(cwd: Path) -> frozenset[str]:
241
+ """Absolute paths of every file git tracks in ``cwd``'s repo (empty if none).
242
+
243
+ Used to recognise inputs that are *sourced by git*: a producer-less file that
244
+ git tracks is restored by ``roar reproduce`` (it checks out the commit), so
245
+ it is NOT unsourced even though nothing in the lineage produced it.
246
+ """
247
+ try:
248
+ root = subprocess.run(
249
+ ["git", "rev-parse", "--show-toplevel"],
250
+ cwd=str(cwd),
251
+ capture_output=True,
252
+ text=True,
253
+ check=False,
254
+ ).stdout.strip()
255
+ if not root:
256
+ return frozenset()
257
+ out = subprocess.run(
258
+ ["git", "ls-files", "-z"], cwd=root, capture_output=True, text=True, check=False
259
+ )
260
+ except OSError:
261
+ return frozenset()
262
+ return frozenset(os.path.join(root, p) for p in out.stdout.split("\0") if p)
263
+
264
+
265
+ def _sourced_by_git(artifact: dict[str, Any] | None, git_tracked: frozenset[str]) -> bool:
266
+ """True iff a producer-less artifact is still recoverable because git tracks it."""
267
+ path = (artifact or {}).get("first_seen_path") or ""
268
+ return bool(path) and os.path.abspath(path) in git_tracked
269
+
270
+
271
+ def _is_unsourced(db_ctx, artifact_id: str, git_tracked: frozenset[str]) -> bool:
272
+ """True iff this artifact won't exist on another machine.
273
+
274
+ Distinct from ``_is_root_artifact``: a producer-with-no-inputs (e.g. a
275
+ ``roar get`` source node, a ``roar run wget`` download, or a deterministic
276
+ generator) is a root but IS sourced — it re-runs on reproduce. An artifact
277
+ with no producer is sourced only if git tracks it (``roar reproduce`` checks
278
+ out the commit and restores it); otherwise it's truly unsourced (a
279
+ pre-existing, un-ingested, uncommitted file).
280
+ """
281
+ produced_by = db_ctx.artifacts.get_jobs(artifact_id).get("produced_by", [])
282
+ if produced_by:
283
+ return False
284
+ return not _sourced_by_git(db_ctx.artifacts.get(artifact_id), git_tracked)
285
+
286
+
287
+ def _make_artifact_summary(
288
+ artifact: dict[str, Any], *, unsourced: bool = False
289
+ ) -> InputArtifactSummary:
205
290
  """Build an InputArtifactSummary from a raw artifact dict."""
206
291
  return InputArtifactSummary(
207
292
  artifact_id=str(artifact["id"]),
@@ -214,10 +299,13 @@ def _make_artifact_summary(artifact: dict[str, Any]) -> InputArtifactSummary:
214
299
  )
215
300
  for h in artifact.get("hashes", [])
216
301
  ],
302
+ unsourced=unsourced,
217
303
  )
218
304
 
219
305
 
220
- def _walk_upstream_roots(db_ctx, start_artifact_ids: list[str]) -> list[InputArtifactSummary]:
306
+ def _walk_upstream_roots(
307
+ db_ctx, start_artifact_ids: list[str], git_tracked: frozenset[str]
308
+ ) -> list[InputArtifactSummary]:
221
309
  """Walk the DAG upstream and collect only root artifacts (no producer)."""
222
310
  roots: dict[str, InputArtifactSummary] = {}
223
311
  visited: set[str] = set()
@@ -235,18 +323,22 @@ def _walk_upstream_roots(db_ctx, start_artifact_ids: list[str]) -> list[InputArt
235
323
  produced_by = jobs.get("produced_by", [])
236
324
 
237
325
  if not produced_by:
238
- # No producer at all this is a root
326
+ # No producer unsourced unless git tracks it (reproduce restores
327
+ # a committed file from the recorded commit).
239
328
  artifact = db_ctx.artifacts.get(artifact_id)
240
329
  if artifact:
241
- roots[artifact_id] = _make_artifact_summary(artifact)
330
+ roots[artifact_id] = _make_artifact_summary(
331
+ artifact, unsourced=not _sourced_by_git(artifact, git_tracked)
332
+ )
242
333
  else:
243
334
  producer = produced_by[0]
244
335
  inputs = db_ctx.jobs.get_inputs(producer["id"])
245
336
  if not inputs:
246
- # Producer has no inputs (e.g., roar get) treat this artifact as a root
337
+ # Producer has no inputs (e.g., roar get / wget / a generator)
338
+ # a root, but SOURCED: it re-runs on reproduce.
247
339
  artifact = db_ctx.artifacts.get(artifact_id)
248
340
  if artifact:
249
- roots[artifact_id] = _make_artifact_summary(artifact)
341
+ roots[artifact_id] = _make_artifact_summary(artifact, unsourced=False)
250
342
  else:
251
343
  for inp in inputs:
252
344
  _trace(inp["artifact_id"])
@@ -259,7 +351,9 @@ def _walk_upstream_roots(db_ctx, start_artifact_ids: list[str]) -> list[InputArt
259
351
  return list(roots.values())
260
352
 
261
353
 
262
- def _get_direct_inputs(db_ctx, start_artifact_ids: list[str]) -> list[InputArtifactSummary]:
354
+ def _get_direct_inputs(
355
+ db_ctx, start_artifact_ids: list[str], git_tracked: frozenset[str]
356
+ ) -> list[InputArtifactSummary]:
263
357
  """Get only the immediate inputs (one level up)."""
264
358
  seen: dict[str, InputArtifactSummary] = {}
265
359
 
@@ -274,13 +368,19 @@ def _get_direct_inputs(db_ctx, start_artifact_ids: list[str]) -> list[InputArtif
274
368
  if aid not in seen:
275
369
  artifact = db_ctx.artifacts.get(aid)
276
370
  if artifact:
277
- seen[aid] = _make_artifact_summary(artifact)
371
+ seen[aid] = _make_artifact_summary(
372
+ artifact, unsourced=_is_unsourced(db_ctx, aid, git_tracked)
373
+ )
278
374
 
279
375
  return list(seen.values())
280
376
 
281
377
 
282
378
  def _walk_upstream_all(
283
- db_ctx, start_artifact_ids: list[str], *, exclude: set[str] | None = None
379
+ db_ctx,
380
+ start_artifact_ids: list[str],
381
+ git_tracked: frozenset[str],
382
+ *,
383
+ exclude: set[str] | None = None,
284
384
  ) -> list[InputArtifactSummary]:
285
385
  """Walk the DAG upstream and collect all artifacts (intermediates + roots)."""
286
386
  exclude = exclude or set()
@@ -296,13 +396,16 @@ def _walk_upstream_all(
296
396
  visited.add(artifact_id)
297
397
  path_stack.add(artifact_id)
298
398
 
399
+ # Fetch producers once; reuse for both the unsourced flag and traversal.
400
+ jobs = db_ctx.artifacts.get_jobs(artifact_id)
401
+ produced_by = jobs.get("produced_by", [])
402
+
299
403
  if artifact_id not in exclude:
300
404
  artifact = db_ctx.artifacts.get(artifact_id)
301
405
  if artifact:
302
- collected[artifact_id] = _make_artifact_summary(artifact)
406
+ unsourced = not produced_by and not _sourced_by_git(artifact, git_tracked)
407
+ collected[artifact_id] = _make_artifact_summary(artifact, unsourced=unsourced)
303
408
 
304
- jobs = db_ctx.artifacts.get_jobs(artifact_id)
305
- produced_by = jobs.get("produced_by", [])
306
409
  if produced_by:
307
410
  producer = produced_by[0]
308
411
  inputs = db_ctx.jobs.get_inputs(producer["id"])
@@ -136,3 +136,5 @@ class InputsQueryRequest:
136
136
  direct: bool = False
137
137
  show_all: bool = False
138
138
  output_json: bool = False
139
+ unsourced: bool = False # show only unsourced inputs (no producer)
140
+ sourced: bool = False # show only sourced inputs (produced/ingested by roar)
@@ -343,6 +343,10 @@ class InputArtifactSummary:
343
343
  path: str
344
344
  size: int
345
345
  hashes: list[ShowHashSummary] = field(default_factory=list)
346
+ # True when nothing tracked produced this artifact (no producing job and not
347
+ # ingested via `roar get` / `roar run wget`). Such inputs won't exist on
348
+ # another machine, so the lineage that consumes them isn't reproducible.
349
+ unsourced: bool = False
346
350
 
347
351
 
348
352
  @dataclass(frozen=True)
@@ -116,6 +116,59 @@ def render_status(request: StatusQueryRequest) -> str:
116
116
  return "\n".join(lines)
117
117
 
118
118
 
119
+ def session_output_paths(roar_dir) -> list[str]:
120
+ """Filesystem paths of the active session's distinct output artifacts.
121
+
122
+ A lightweight counterpart to ``build_status_summary``: no publish-auth
123
+ resolution and no canonical dag-hash — just the paths. Callers like the
124
+ artifact-path reproducibility check need only the paths, and must not trigger
125
+ auth side effects (resolving SSH/creator identity would, e.g., inject a
126
+ signed request into an otherwise-anonymous publish).
127
+ """
128
+ with create_query_database_context(roar_dir) as db_ctx:
129
+ session = db_ctx.sessions.get_active()
130
+ if not session:
131
+ return []
132
+ distinct_outputs = getattr(db_ctx.jobs, "get_distinct_outputs_by_session", None)
133
+ if callable(distinct_outputs):
134
+ outputs = distinct_outputs(session["id"])
135
+ else:
136
+ seen: set[int | str] = set()
137
+ outputs = []
138
+ for job in db_ctx.jobs.get_by_session(session["id"], limit=10000):
139
+ for output in db_ctx.jobs.get_outputs(job["id"]):
140
+ if output["artifact_id"] not in seen:
141
+ seen.add(output["artifact_id"])
142
+ outputs.append(output)
143
+ return [str(output["path"]) for output in outputs if output["path"]]
144
+
145
+
146
+ def render_untracked_dirs(request: StatusQueryRequest, cwd) -> str:
147
+ """Focused view: the session's output artifacts whose directory won't exist
148
+ on a clean checkout (untracked in-repo dirs, or paths outside the repo).
149
+
150
+ Backs the `all artifact paths in tracked directories` reproducibility check;
151
+ surfaced as `roar status --untracked-dirs` so the user can see exactly which
152
+ paths the check is flagging."""
153
+ from ..reproducibility.report import untracked_artifact_dirs
154
+
155
+ paths = untracked_artifact_dirs(request.roar_dir, cwd)
156
+ if paths is None:
157
+ return "Not in a git repository — artifact-path tracking doesn't apply."
158
+ if not paths:
159
+ return "All artifact paths are in tracked directories."
160
+
161
+ lines = [f"Artifacts in untracked directories ({len(paths)}):"]
162
+ lines.extend(f" {path}" for path in paths)
163
+ lines.append("")
164
+ lines.append(
165
+ "These directories won't exist on a clean checkout, so reproduction may "
166
+ "fail unless the run recreates them."
167
+ )
168
+ lines.append("Add a .gitkeep (or any tracked file) to each so a fresh checkout includes it.")
169
+ return "\n".join(lines)
170
+
171
+
119
172
  def build_status_summary(request: StatusQueryRequest) -> StatusSummary:
120
173
  """Build a typed summary of the active session status."""
121
174
  with create_query_database_context(request.roar_dir) as db_ctx: