roar-cli 0.3.7__tar.gz → 0.4.0__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 (439) hide show
  1. {roar_cli-0.3.7 → roar_cli-0.4.0}/PKG-INFO +1 -1
  2. {roar_cli-0.3.7 → roar_cli-0.4.0}/pyproject.toml +1 -1
  3. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/publish/register_execution.py +19 -6
  4. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/publish/service.py +17 -7
  5. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/publish/view_edges.py +15 -6
  6. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/query/__init__.py +12 -0
  7. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/query/requests.py +52 -0
  8. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/query/results.py +74 -0
  9. roar_cli-0.4.0/roar/application/query/tag.py +224 -0
  10. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/run/execution.py +4 -0
  11. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/run/requests.py +2 -0
  12. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/run/service.py +6 -0
  13. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/system_labels.py +7 -1
  14. roar_cli-0.4.0/roar/application/tags.py +746 -0
  15. roar_cli-0.4.0/roar/cli/_tag_kinds.py +69 -0
  16. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/command_registry.py +7 -0
  17. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/commands/__init__.py +1 -0
  18. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/commands/register.py +106 -3
  19. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/commands/run.py +39 -0
  20. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/commands/status.py +10 -0
  21. roar_cli-0.4.0/roar/cli/commands/tag.py +241 -0
  22. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/publish_intent.py +16 -1
  23. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/core/label_constants.py +12 -0
  24. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/core/models/run.py +2 -0
  25. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/db/services/job_recording.py +75 -5
  26. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/recording/job_recording.py +2 -0
  27. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/reproduction/pipeline_executor.py +29 -19
  28. roar_cli-0.4.0/roar/execution/runtime/active_runs.py +144 -0
  29. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/runtime/coordinator.py +9 -0
  30. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/config/access.py +8 -0
  31. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/config/schema.py +12 -0
  32. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/presenters/show_renderer.py +30 -2
  33. {roar_cli-0.3.7 → roar_cli-0.4.0}/LICENSE +0 -0
  34. {roar_cli-0.3.7 → roar_cli-0.4.0}/README.md +0 -0
  35. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/__init__.py +0 -0
  36. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/__main__.py +0 -0
  37. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/analyzers/__init__.py +0 -0
  38. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/analyzers/base.py +0 -0
  39. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/analyzers/experiment_trackers.py +0 -0
  40. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/__init__.py +0 -0
  41. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/composite/__init__.py +0 -0
  42. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/composite/canonical.py +0 -0
  43. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/composite/detect.py +0 -0
  44. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/composite/qualifying.py +0 -0
  45. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/get/__init__.py +0 -0
  46. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/get/requests.py +0 -0
  47. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/get/results.py +0 -0
  48. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/get/service.py +0 -0
  49. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/get/transfer.py +0 -0
  50. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/git.py +0 -0
  51. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/label_rendering.py +0 -0
  52. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/labels.py +0 -0
  53. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/lookup/__init__.py +0 -0
  54. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/lookup/models.py +0 -0
  55. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/lookup/policy.py +0 -0
  56. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/lookup/refs.py +0 -0
  57. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/lookup/remote_artifacts.py +0 -0
  58. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/lookup/runner.py +0 -0
  59. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/publish/__init__.py +0 -0
  60. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/publish/anchor_attribution.py +0 -0
  61. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/publish/blake3_upgrade.py +0 -0
  62. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/publish/collection.py +0 -0
  63. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/publish/composite_builder.py +0 -0
  64. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/publish/composites.py +0 -0
  65. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/publish/datasets.py +0 -0
  66. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/publish/form_composites.py +0 -0
  67. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/publish/git_remote.py +0 -0
  68. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/publish/job_links.py +0 -0
  69. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/publish/job_preparation.py +0 -0
  70. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/publish/lineage.py +0 -0
  71. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/publish/lineage_composite_formation.py +0 -0
  72. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/publish/lineage_composites.py +0 -0
  73. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/publish/metadata.py +0 -0
  74. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/publish/put_composites.py +0 -0
  75. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/publish/put_execution.py +0 -0
  76. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/publish/put_preparation.py +0 -0
  77. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/publish/register_preparation.py +0 -0
  78. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/publish/register_preview_jobs.py +0 -0
  79. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/publish/register_tag_push.py +0 -0
  80. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/publish/registration.py +0 -0
  81. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/publish/registration_package.py +0 -0
  82. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/publish/remote_job_uids.py +0 -0
  83. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/publish/remote_registry.py +0 -0
  84. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/publish/requests.py +0 -0
  85. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/publish/results.py +0 -0
  86. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/publish/runtime.py +0 -0
  87. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/publish/secrets.py +0 -0
  88. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/publish/session.py +0 -0
  89. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/publish/source_resolution.py +0 -0
  90. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/publish/targets.py +0 -0
  91. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/query/dag.py +0 -0
  92. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/query/db_status.py +0 -0
  93. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/query/diff.py +0 -0
  94. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/query/diff_engine.py +0 -0
  95. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/query/diff_graph.py +0 -0
  96. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/query/diff_refs.py +0 -0
  97. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/query/git_readiness.py +0 -0
  98. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/query/inputs.py +0 -0
  99. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/query/label.py +0 -0
  100. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/query/lineage.py +0 -0
  101. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/query/log.py +0 -0
  102. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/query/show.py +0 -0
  103. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/query/status.py +0 -0
  104. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/reproduce/__init__.py +0 -0
  105. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/reproduce/environment.py +0 -0
  106. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/reproduce/lookup.py +0 -0
  107. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/reproduce/requests.py +0 -0
  108. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/reproduce/results.py +0 -0
  109. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/reproduce/service.py +0 -0
  110. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/reproducibility/__init__.py +0 -0
  111. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/reproducibility/report.py +0 -0
  112. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/run/__init__.py +0 -0
  113. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/run/dag_references.py +0 -0
  114. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/run/dirty_tree_classify.py +0 -0
  115. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/run/dirty_tree_error.py +0 -0
  116. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/run/gitignore_suggest.py +0 -0
  117. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/run/output_followup.py +0 -0
  118. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/run/verbosity.py +0 -0
  119. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/workflow/__init__.py +0 -0
  120. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/workflow/requests.py +0 -0
  121. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/workflow/results.py +0 -0
  122. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/application/workflow/service.py +0 -0
  123. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/auth_store.py +0 -0
  124. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/backends/__init__.py +0 -0
  125. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/backends/local/__init__.py +0 -0
  126. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/backends/local/plugin.py +0 -0
  127. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/backends/osmo/__init__.py +0 -0
  128. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/backends/osmo/config.py +0 -0
  129. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/backends/osmo/export.py +0 -0
  130. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/backends/osmo/host_execution.py +0 -0
  131. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/backends/osmo/lineage.py +0 -0
  132. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/backends/osmo/plugin.py +0 -0
  133. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/backends/osmo/runtime_bundle.py +0 -0
  134. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/backends/osmo/submit.py +0 -0
  135. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/backends/osmo/workflow.py +0 -0
  136. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/backends/ray/__init__.py +0 -0
  137. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/backends/ray/_agent_names.py +0 -0
  138. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/backends/ray/collector.py +0 -0
  139. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/backends/ray/config.py +0 -0
  140. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/backends/ray/constants.py +0 -0
  141. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/backends/ray/env_contract.py +0 -0
  142. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/backends/ray/fragment.py +0 -0
  143. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/backends/ray/fragment_reconstituter.py +0 -0
  144. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/backends/ray/node_agent.py +0 -0
  145. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/backends/ray/plugin.py +0 -0
  146. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/backends/ray/proxy_fragments.py +0 -0
  147. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/backends/ray/roar_worker.py +0 -0
  148. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/backends/ray/runtime_hooks.py +0 -0
  149. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/backends/ray/s3_key_paths.py +0 -0
  150. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/backends/ray/submit.py +0 -0
  151. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/backends/ray/submit_context.py +0 -0
  152. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/__init__.py +0 -0
  153. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/_format.py +0 -0
  154. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/commands/auth.py +0 -0
  155. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/commands/build.py +0 -0
  156. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/commands/config.py +0 -0
  157. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/commands/dag.py +0 -0
  158. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/commands/db.py +0 -0
  159. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/commands/diff.py +0 -0
  160. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/commands/env.py +0 -0
  161. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/commands/export_registration_package.py +0 -0
  162. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/commands/filter.py +0 -0
  163. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/commands/get.py +0 -0
  164. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/commands/init.py +0 -0
  165. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/commands/init_agents.py +0 -0
  166. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/commands/inputs.py +0 -0
  167. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/commands/label.py +0 -0
  168. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/commands/lineage.py +0 -0
  169. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/commands/log.py +0 -0
  170. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/commands/login.py +0 -0
  171. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/commands/logout.py +0 -0
  172. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/commands/osmo.py +0 -0
  173. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/commands/pop.py +0 -0
  174. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/commands/projects.py +0 -0
  175. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/commands/proxy.py +0 -0
  176. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/commands/put.py +0 -0
  177. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/commands/reproduce.py +0 -0
  178. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/commands/reset.py +0 -0
  179. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/commands/scope.py +0 -0
  180. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/commands/session.py +0 -0
  181. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/commands/show.py +0 -0
  182. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/commands/telemetry.py +0 -0
  183. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/commands/tracer.py +0 -0
  184. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/commands/tui.py +0 -0
  185. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/commands/whoami.py +0 -0
  186. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/commands/workflow.py +0 -0
  187. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/context.py +0 -0
  188. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/decorators.py +0 -0
  189. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/templates/agents/SKILL.md.tmpl +0 -0
  190. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/cli/templates/agents/agents_section.md.tmpl +0 -0
  191. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/core/__init__.py +0 -0
  192. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/core/bootstrap.py +0 -0
  193. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/core/canonical_session.py +0 -0
  194. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/core/digests.py +0 -0
  195. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/core/dto/__init__.py +0 -0
  196. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/core/dto/registration.py +0 -0
  197. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/core/exceptions.py +0 -0
  198. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/core/interfaces/__init__.py +0 -0
  199. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/core/interfaces/config.py +0 -0
  200. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/core/interfaces/lineage.py +0 -0
  201. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/core/interfaces/logger.py +0 -0
  202. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/core/interfaces/presenter.py +0 -0
  203. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/core/interfaces/provenance.py +0 -0
  204. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/core/interfaces/registration.py +0 -0
  205. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/core/interfaces/repositories.py +0 -0
  206. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/core/interfaces/reproduction.py +0 -0
  207. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/core/interfaces/run.py +0 -0
  208. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/core/interfaces/services.py +0 -0
  209. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/core/interfaces/telemetry.py +0 -0
  210. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/core/interfaces/vcs.py +0 -0
  211. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/core/label_origins.py +0 -0
  212. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/core/logging.py +0 -0
  213. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/core/models/__init__.py +0 -0
  214. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/core/models/artifact.py +0 -0
  215. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/core/models/base.py +0 -0
  216. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/core/models/dag.py +0 -0
  217. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/core/models/dataset_identifier.py +0 -0
  218. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/core/models/glaas.py +0 -0
  219. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/core/models/job.py +0 -0
  220. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/core/models/lineage.py +0 -0
  221. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/core/models/provenance.py +0 -0
  222. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/core/models/session.py +0 -0
  223. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/core/models/telemetry.py +0 -0
  224. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/core/models/vcs.py +0 -0
  225. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/core/operation_metadata.py +0 -0
  226. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/core/session_hash.py +0 -0
  227. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/core/step_name.py +0 -0
  228. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/core/tracer_modes.py +0 -0
  229. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/core/validation.py +0 -0
  230. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/db/__init__.py +0 -0
  231. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/db/context.py +0 -0
  232. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/db/engine.py +0 -0
  233. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/db/hashing/__init__.py +0 -0
  234. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/db/hashing/backend.py +0 -0
  235. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/db/hashing/blake3.py +0 -0
  236. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/db/models.py +0 -0
  237. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/db/query_context.py +0 -0
  238. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/db/repositories/__init__.py +0 -0
  239. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/db/repositories/artifact.py +0 -0
  240. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/db/repositories/collection.py +0 -0
  241. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/db/repositories/composite.py +0 -0
  242. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/db/repositories/hash_cache.py +0 -0
  243. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/db/repositories/job.py +0 -0
  244. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/db/repositories/label.py +0 -0
  245. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/db/repositories/session.py +0 -0
  246. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/db/schema.py +0 -0
  247. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/db/services/__init__.py +0 -0
  248. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/db/services/hashing.py +0 -0
  249. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/db/services/lineage.py +0 -0
  250. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/db/services/session.py +0 -0
  251. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/db/step_priority.py +0 -0
  252. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/__init__.py +0 -0
  253. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/cluster/__init__.py +0 -0
  254. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/cluster/bridge.py +0 -0
  255. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/cluster/proxy.py +0 -0
  256. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/cluster/proxy_config.py +0 -0
  257. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/fragments/__init__.py +0 -0
  258. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/fragments/lineage.py +0 -0
  259. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/fragments/models.py +0 -0
  260. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/fragments/reconstitution.py +0 -0
  261. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/fragments/sessions.py +0 -0
  262. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/fragments/transport.py +0 -0
  263. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/framework/__init__.py +0 -0
  264. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/framework/contract.py +0 -0
  265. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/framework/planning.py +0 -0
  266. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/framework/registry.py +0 -0
  267. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/framework/runtime_imports.py +0 -0
  268. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/provenance/__init__.py +0 -0
  269. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/provenance/assembler.py +0 -0
  270. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/provenance/build_pip_collector.py +0 -0
  271. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/provenance/build_tool_collector.py +0 -0
  272. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/provenance/data_loader.py +0 -0
  273. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/provenance/file_filter.py +0 -0
  274. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/provenance/package_collector.py +0 -0
  275. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/provenance/process_summarizer.py +0 -0
  276. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/provenance/runtime_collector.py +0 -0
  277. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/provenance/service.py +0 -0
  278. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/recording/__init__.py +0 -0
  279. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/recording/dataset_identifier.py +0 -0
  280. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/recording/dataset_metadata.py +0 -0
  281. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/recording/dataset_profile.py +0 -0
  282. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/reproduction/__init__.py +0 -0
  283. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/reproduction/environment_setup.py +0 -0
  284. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/reproduction/installers.py +0 -0
  285. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/reproduction/pipeline_metadata.py +0 -0
  286. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/runtime/__init__.py +0 -0
  287. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/runtime/abi_probe.py +0 -0
  288. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/runtime/backup.py +0 -0
  289. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/runtime/driver_entrypoint.py +0 -0
  290. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/runtime/errors.py +0 -0
  291. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/runtime/host_execution.py +0 -0
  292. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/runtime/inject/__init__.py +0 -0
  293. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/runtime/inject/sitecustomize.py +0 -0
  294. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/runtime/inject/support.py +0 -0
  295. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/runtime/inject/tracker.py +0 -0
  296. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/runtime/lazy_install.py +0 -0
  297. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/runtime/proxy_resource.py +0 -0
  298. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/runtime/resources.py +0 -0
  299. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/runtime/signal_handler.py +0 -0
  300. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/runtime/tracer.py +0 -0
  301. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/runtime/tracer_backends.py +0 -0
  302. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/runtime/tracer_banner.py +0 -0
  303. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/execution/runtime/worker_bootstrap.py +0 -0
  304. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/filters/__init__.py +0 -0
  305. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/filters/files.py +0 -0
  306. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/filters/omit.py +0 -0
  307. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/glaas_auth.py +0 -0
  308. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/glaas_client.py +0 -0
  309. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/__init__.py +0 -0
  310. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/bootstrap.py +0 -0
  311. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/config/__init__.py +0 -0
  312. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/config/loader.py +0 -0
  313. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/config/raw.py +0 -0
  314. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/discovery.py +0 -0
  315. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/download/__init__.py +0 -0
  316. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/download/base.py +0 -0
  317. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/download/gcs.py +0 -0
  318. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/download/get.py +0 -0
  319. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/download/hf.py +0 -0
  320. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/download/http.py +0 -0
  321. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/download/noop.py +0 -0
  322. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/download/s3.py +0 -0
  323. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/git/__init__.py +0 -0
  324. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/git/base.py +0 -0
  325. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/git/context.py +0 -0
  326. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/git/provider.py +0 -0
  327. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/glaas/__init__.py +0 -0
  328. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/glaas/auth.py +0 -0
  329. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/glaas/client.py +0 -0
  330. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/glaas/fragment_streamer.py +0 -0
  331. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/glaas/registration/__init__.py +0 -0
  332. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/glaas/registration/_artifact_ref.py +0 -0
  333. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/glaas/registration/artifact.py +0 -0
  334. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/glaas/registration/coordinator.py +0 -0
  335. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/glaas/registration/job.py +0 -0
  336. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/glaas/registration/session.py +0 -0
  337. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/glaas/transport.py +0 -0
  338. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/registry.py +0 -0
  339. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/resolution.py +0 -0
  340. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/storage/__init__.py +0 -0
  341. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/storage/base.py +0 -0
  342. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/storage/gcs.py +0 -0
  343. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/storage/memory.py +0 -0
  344. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/storage/noop.py +0 -0
  345. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/storage/publish.py +0 -0
  346. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/storage/s3.py +0 -0
  347. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/telemetry/__init__.py +0 -0
  348. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/telemetry/base.py +0 -0
  349. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/integrations/telemetry/wandb.py +0 -0
  350. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/presenters/__init__.py +0 -0
  351. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/presenters/console.py +0 -0
  352. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/presenters/dag_data_builder.py +0 -0
  353. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/presenters/dag_renderer.py +0 -0
  354. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/presenters/diff_renderer.py +0 -0
  355. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/presenters/formatting.py +0 -0
  356. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/presenters/null.py +0 -0
  357. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/presenters/run_report.py +0 -0
  358. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/presenters/spinner.py +0 -0
  359. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/presenters/terminal.py +0 -0
  360. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/publish_auth.py +0 -0
  361. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/require.py +0 -0
  362. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/scope_config.py +0 -0
  363. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/telemetry/__init__.py +0 -0
  364. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/telemetry/_io.py +0 -0
  365. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/telemetry/capabilities.py +0 -0
  366. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/telemetry/config.py +0 -0
  367. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/telemetry/hooks.py +0 -0
  368. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/telemetry/install.py +0 -0
  369. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/telemetry/paths.py +0 -0
  370. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/telemetry/payload.py +0 -0
  371. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/telemetry/queue.py +0 -0
  372. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/telemetry/stats.py +0 -0
  373. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/telemetry/uploader.py +0 -0
  374. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/tui/__init__.py +0 -0
  375. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/tui/app.py +0 -0
  376. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/tui/data.py +0 -0
  377. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/tui/screens/__init__.py +0 -0
  378. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/tui/screens/config_editor.py +0 -0
  379. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/tui/screens/label_editor.py +0 -0
  380. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/tui/screens/launcher.py +0 -0
  381. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/tui/screens/log.py +0 -0
  382. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/tui/screens/main.py +0 -0
  383. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/tui/screens/search.py +0 -0
  384. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/tui/screens/session_picker.py +0 -0
  385. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/tui/tmux.py +0 -0
  386. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/tui/widgets/__init__.py +0 -0
  387. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/tui/widgets/detail.py +0 -0
  388. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/utils/__init__.py +0 -0
  389. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/utils/cloud.py +0 -0
  390. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/utils/git_url.py +0 -0
  391. {roar_cli-0.3.7 → roar_cli-0.4.0}/roar/version_check.py +0 -0
  392. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/Cargo.lock +0 -0
  393. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/Cargo.toml +0 -0
  394. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/crates/artifact-hash-core/Cargo.toml +0 -0
  395. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/crates/artifact-hash-core/src/lib.rs +0 -0
  396. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/crates/artifact-hash-py/Cargo.toml +0 -0
  397. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/crates/artifact-hash-py/src/lib.rs +0 -0
  398. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/crates/tracer-fd/Cargo.toml +0 -0
  399. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/crates/tracer-fd/src/lib.rs +0 -0
  400. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/crates/tracer-runtime/Cargo.toml +0 -0
  401. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/crates/tracer-runtime/src/lib.rs +0 -0
  402. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/crates/tracer-schema/Cargo.toml +0 -0
  403. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/crates/tracer-schema/src/lib.rs +0 -0
  404. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/services/proxy/Cargo.lock +0 -0
  405. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/services/proxy/Cargo.toml +0 -0
  406. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/services/proxy/src/forward.rs +0 -0
  407. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/services/proxy/src/main.rs +0 -0
  408. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/services/proxy/src/s3.rs +0 -0
  409. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/tracers/ebpf/common/Cargo.toml +0 -0
  410. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/tracers/ebpf/common/src/lib.rs +0 -0
  411. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/tracers/ebpf/probe/Cargo.toml +0 -0
  412. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/tracers/ebpf/probe/rust-toolchain.toml +0 -0
  413. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/tracers/ebpf/probe/src/main.rs +0 -0
  414. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/tracers/ebpf/userspace/Cargo.toml +0 -0
  415. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/tracers/ebpf/userspace/build.rs +0 -0
  416. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/tracers/ebpf/userspace/src/attach.rs +0 -0
  417. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/tracers/ebpf/userspace/src/bin/roard.rs +0 -0
  418. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/tracers/ebpf/userspace/src/client.rs +0 -0
  419. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/tracers/ebpf/userspace/src/daemon.rs +0 -0
  420. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/tracers/ebpf/userspace/src/events.rs +0 -0
  421. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/tracers/ebpf/userspace/src/ipc.rs +0 -0
  422. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/tracers/ebpf/userspace/src/lib.rs +0 -0
  423. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/tracers/ebpf/userspace/src/main.rs +0 -0
  424. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/tracers/ebpf/userspace/src/state.rs +0 -0
  425. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/tracers/preload/Cargo.toml +0 -0
  426. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/tracers/preload/build.rs +0 -0
  427. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/tracers/preload/src/bin/io_fixture.rs +0 -0
  428. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/tracers/preload/src/interpose.c +0 -0
  429. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/tracers/preload/src/ipc.rs +0 -0
  430. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/tracers/preload/src/lib.rs +0 -0
  431. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/tracers/preload/src/main.rs +0 -0
  432. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/tracers/preload/tests/comprehensive.rs +0 -0
  433. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/tracers/preload/tests/standalone.rs +0 -0
  434. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/tracers/ptrace/Cargo.toml +0 -0
  435. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/tracers/ptrace/rustfmt.toml +0 -0
  436. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/tracers/ptrace/src/arch.rs +0 -0
  437. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/tracers/ptrace/src/main.rs +0 -0
  438. {roar_cli-0.3.7 → roar_cli-0.4.0}/rust/tracers/ptrace/src/seccomp.rs +0 -0
  439. {roar_cli-0.3.7 → roar_cli-0.4.0}/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.7
3
+ Version: 0.4.0
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.7"
8
+ version = "0.4.0"
9
9
  description = "Reproducibility and provenance tracker for ML training pipelines"
10
10
  authors = [
11
11
  { name="TReqs Team", email="info@treqs.ai" }
@@ -222,8 +222,15 @@ class RegisterService:
222
222
  skip_confirmation: bool,
223
223
  confirm_callback: Callable[[list[str]], bool] | None,
224
224
  prepared: PreparedRegisterExecution,
225
+ composite_leaf_hashes: frozenset[str] = frozenset(),
225
226
  ) -> RegisterResult:
226
- """Register already-collected local lineage with GLaaS."""
227
+ """Register already-collected local lineage with GLaaS.
228
+
229
+ ``composite_leaf_hashes`` are true composite-member hashes subsumed into a view
230
+ edge (see ``_prepare_view_edges_for_lineage``) — they have no session-scoped edge
231
+ on GLaaS, so they're excluded from label sync even though they still appear in
232
+ ``lineage.artifacts`` for ordinary artifact registration.
233
+ """
227
234
  self._logger.debug(
228
235
  "Collected lineage: %d jobs, %d artifacts",
229
236
  len(lineage.jobs),
@@ -276,6 +283,12 @@ class RegisterService:
276
283
  omit_filter=omit_filter,
277
284
  )
278
285
 
286
+ label_artifacts = (
287
+ [a for a in lineage.artifacts if a.get("hash") not in composite_leaf_hashes]
288
+ if composite_leaf_hashes
289
+ else lineage.artifacts
290
+ )
291
+
279
292
  registration_jobs = order_jobs_for_registration(
280
293
  normalize_jobs_for_registration(lineage.jobs)
281
294
  )
@@ -344,7 +357,7 @@ class RegisterService:
344
357
  session_id=session_id,
345
358
  session_hash=finalized_session_hash,
346
359
  jobs=remote_registration_jobs,
347
- artifacts=lineage.artifacts,
360
+ artifacts=label_artifacts,
348
361
  errors=registration_errors,
349
362
  )
350
363
  elif batch_result.jobs_failed == 0 and batch_result.links_failed == 0:
@@ -391,7 +404,7 @@ class RegisterService:
391
404
  session_id=session_id,
392
405
  session_hash=finalized_session_hash,
393
406
  jobs=remote_registration_jobs,
394
- artifacts=lineage.artifacts,
407
+ artifacts=label_artifacts,
395
408
  errors=registration_errors,
396
409
  )
397
410
  except Exception as e:
@@ -411,7 +424,7 @@ class RegisterService:
411
424
  session_id=session_id,
412
425
  session_hash=finalized_session_hash,
413
426
  jobs=remote_registration_jobs,
414
- artifacts=lineage.artifacts,
427
+ artifacts=label_artifacts,
415
428
  errors=registration_errors,
416
429
  )
417
430
  else:
@@ -456,7 +469,7 @@ class RegisterService:
456
469
  ),
457
470
  db_ctx=db_ctx,
458
471
  session_id=session_id,
459
- label_artifacts=lineage.artifacts,
472
+ label_artifacts=label_artifacts,
460
473
  )
461
474
  else:
462
475
  batch_result = register_publish_lineage(
@@ -473,7 +486,7 @@ class RegisterService:
473
486
  ),
474
487
  db_ctx=None,
475
488
  session_id=None,
476
- label_artifacts=lineage.artifacts,
489
+ label_artifacts=label_artifacts,
477
490
  )
478
491
  registration_errors.extend(batch_result.errors)
479
492
 
@@ -496,7 +496,7 @@ def _load_remote_job_uid_mapping(*, roar_dir: Path, session_id: Any) -> dict[str
496
496
 
497
497
  def _prepare_view_edges_for_lineage(
498
498
  *, roar_dir: Path, lineage: Any, logger: Any
499
- ) -> dict[str, list[Any]]:
499
+ ) -> tuple[dict[str, list[Any]], set[str]]:
500
500
  """Compute consumes/produces view edges per job and prune the subsumed leaves in-place.
501
501
 
502
502
  A job that read part of a dataset gets a ``consumes`` view edge over its inputs; a job
@@ -505,15 +505,21 @@ def _prepare_view_edges_for_lineage(
505
505
  and any anchor linked as a plain input/output — are removed from the bundle so the job
506
506
  links the dataset *view* (job -> view -> anchor -> leaves), not the loose leaves or the
507
507
  anchor directly. The anchor composite stays in ``lineage.artifacts`` (already
508
- collected) so it is still registered. Returns ``{job_uid: [view_edge, ...]}`` to push
509
- after the main registration.
508
+ collected) so it is still registered.
509
+
510
+ Returns ``({job_uid: [view_edge, ...]}, composite_leaf_hashes)``: the view edges to
511
+ push after the main registration, and the union of true component/leaf hashes (never
512
+ the anchor's own hash) subsumed across all jobs — a leaf has no session-scoped edge on
513
+ GLaaS, so the caller uses this set to keep leaf label/tag documents out of publish-time
514
+ label sync too.
510
515
  """
511
516
  from .view_edges import resolve_view_edges_for_job
512
517
 
513
518
  jobs = getattr(lineage, "jobs", []) or []
514
519
  if not jobs:
515
- return {}
520
+ return {}, set()
516
521
  view_edges_by_job: dict[str, list[Any]] = {}
522
+ composite_leaf_hashes: set[str] = set()
517
523
  with create_database_context(roar_dir) as db:
518
524
  for job in jobs:
519
525
  if not isinstance(job, dict):
@@ -530,7 +536,7 @@ def _prepare_view_edges_for_lineage(
530
536
  hashes = list(job.get(hashes_key) or [])
531
537
  if not hashes:
532
538
  continue
533
- resolved, prune = resolve_view_edges_for_job(
539
+ resolved, prune, leaf_hashes = resolve_view_edges_for_job(
534
540
  db_ctx=db, input_hashes=hashes, relation=relation
535
541
  )
536
542
  if not resolved:
@@ -539,9 +545,10 @@ def _prepare_view_edges_for_lineage(
539
545
  job[hashes_key] = [h for h in hashes if h not in prune]
540
546
  if isinstance(job.get(items_key), list):
541
547
  job[items_key] = [i for i in job[items_key] if i.get("hash") not in prune]
548
+ composite_leaf_hashes |= leaf_hashes
542
549
  if edges:
543
550
  view_edges_by_job[str(job_uid)] = edges
544
- return view_edges_by_job
551
+ return view_edges_by_job, composite_leaf_hashes
545
552
 
546
553
 
547
554
  def register_lineage_target(request: RegisterLineageRequest) -> RegisterLineageResponse:
@@ -628,13 +635,15 @@ def register_lineage_target(request: RegisterLineageRequest) -> RegisterLineageR
628
635
  # bloom over the touched leaves) and prune the subsumed leaves from the bundle.
629
636
  # Pushed after the main registration. Best-effort.
630
637
  view_edges_by_job: dict[str, list[Any]] = {}
638
+ composite_leaf_hashes: frozenset[str] = frozenset()
631
639
  if not request.dry_run:
632
640
  try:
633
- view_edges_by_job = _prepare_view_edges_for_lineage(
641
+ view_edges_by_job, leaf_hashes = _prepare_view_edges_for_lineage(
634
642
  roar_dir=request.roar_dir,
635
643
  lineage=collected_lineage.lineage,
636
644
  logger=logger,
637
645
  )
646
+ composite_leaf_hashes = frozenset(leaf_hashes)
638
647
  except Exception as exc: # view-edge prep is best-effort
639
648
  logger.debug("view-edge preparation skipped: %s", exc)
640
649
 
@@ -728,6 +737,7 @@ def register_lineage_target(request: RegisterLineageRequest) -> RegisterLineageR
728
737
  skip_confirmation=request.skip_confirmation,
729
738
  confirm_callback=request.confirm_callback,
730
739
  prepared=prepared,
740
+ composite_leaf_hashes=composite_leaf_hashes,
731
741
  )
732
742
 
733
743
  # Push the consumes view edges now that the jobs + the anchor composite are
@@ -115,16 +115,23 @@ def resolve_view_edges_for_job(
115
115
  db_ctx: Any,
116
116
  input_hashes: list[str],
117
117
  relation: Literal["consumes", "produces"] = "consumes",
118
- ) -> tuple[list[dict[str, Any]], set[str]]:
118
+ ) -> tuple[list[dict[str, Any]], set[str], set[str]]:
119
119
  """Resolve a job's leaf *hashes* into view edges + hashes to prune.
120
120
 
121
121
  Works from the collected-lineage hashes (not artifact ids). ``relation`` is the side
122
122
  being resolved: ``consumes`` over a job's input hashes (a run that read part of a
123
123
  dataset) or ``produces`` over its output hashes (a run that wrote one). The resolution
124
124
  is identical either way — each leaf is matched to the anchor composite(s) that carry
125
- it as a component. Returns ``(view_edges, prune_hashes)`` — the second being the leaf
126
- hashes that collapse into a view edge plus any anchor composite hash linked as a plain
127
- input/output (the view edge replaces it).
125
+ it as a component. Returns ``(view_edges, prune_hashes, leaf_hashes)``:
126
+
127
+ - ``prune_hashes``: the leaf hashes that collapse into a view edge plus any anchor
128
+ composite hash linked as a plain input/output (the view edge replaces it). Used to
129
+ drop these from a job's plain input/output edges.
130
+ - ``leaf_hashes``: strictly the true component/leaf hashes subsumed into a view edge
131
+ (a subset of ``prune_hashes`` that excludes a directly-linked anchor's own hash).
132
+ A composite member never has its own session-scoped edge on GLaaS — it has no
133
+ standing to carry its own labels/tags either, so callers use this set to keep
134
+ per-leaf label/tag documents out of publish-time label sync.
128
135
 
129
136
  BOUNDARY: matching uses ``find_by_component_digest``, which only knows the anchor's
130
137
  *stored* components (capped at ``_MAX_STORED_COMPONENTS`` = 1000). For a dataset with
@@ -138,7 +145,7 @@ def resolve_view_edges_for_job(
138
145
  artifacts_repo: Any = optional_repo(db_ctx, "artifacts")
139
146
  composites_repo: Any = optional_repo(db_ctx, "composites")
140
147
  if artifacts_repo is None or composites_repo is None:
141
- return [], set()
148
+ return [], set(), set()
142
149
 
143
150
  # anchor_id -> {"algorithm": str, "leaves": set, "shards": set}
144
151
  by_anchor: dict[str, dict[str, Any]] = {}
@@ -174,6 +181,7 @@ def resolve_view_edges_for_job(
174
181
  _attribute(blake3_digest, "blake3", digest)
175
182
 
176
183
  view_edges: list[dict[str, Any]] = []
184
+ leaf_hashes: set[str] = set()
177
185
  for anchor_id, bucket in by_anchor.items():
178
186
  anchor = artifacts_repo.get(anchor_id)
179
187
  anchor_digest = _primary_composite_digest(anchor)
@@ -189,8 +197,9 @@ def resolve_view_edges_for_job(
189
197
  )
190
198
  )
191
199
  prune |= bucket["shards"]
200
+ leaf_hashes |= bucket["shards"]
192
201
 
193
- return view_edges, prune
202
+ return view_edges, prune, leaf_hashes
194
203
 
195
204
 
196
205
  def _primary_composite_digest(artifact: dict[str, Any] | None) -> str | None:
@@ -21,6 +21,10 @@ _EXPORTS = {
21
21
  "LogQueryRequest": ".requests",
22
22
  "ShowQueryRequest": ".requests",
23
23
  "StatusQueryRequest": ".requests",
24
+ "TagAddRequest": ".requests",
25
+ "TagHistoryRequest": ".requests",
26
+ "TagRmRequest": ".requests",
27
+ "TagShowRequest": ".requests",
24
28
  "LabelCurrentSummary": ".results",
25
29
  "LabelHistorySummary": ".results",
26
30
  "LineageSummary": ".results",
@@ -37,6 +41,10 @@ _EXPORTS = {
37
41
  "build_show_labels_summary": ".label",
38
42
  "build_sync_labels_summary": ".label",
39
43
  "build_unset_labels_summary": ".label",
44
+ "build_tag_add_summary": ".tag",
45
+ "build_tag_history_summary": ".tag",
46
+ "build_tag_rm_summary": ".tag",
47
+ "build_tag_show_summary": ".tag",
40
48
  "copy_labels": ".label",
41
49
  "label_history": ".label",
42
50
  "remote_label_history": ".label",
@@ -51,6 +59,10 @@ _EXPORTS = {
51
59
  "set_labels": ".label",
52
60
  "show_labels": ".label",
53
61
  "sync_labels": ".label",
62
+ "tag_add": ".tag",
63
+ "tag_history": ".tag",
64
+ "tag_rm": ".tag",
65
+ "tag_show": ".tag",
54
66
  "unset_labels": ".label",
55
67
  }
56
68
 
@@ -176,3 +176,55 @@ class InputsQueryRequest:
176
176
  output_json: bool = False
177
177
  unsourced: bool = False # show only unsourced inputs (no producer)
178
178
  sourced: bool = False # show only sourced inputs (produced/ingested by roar)
179
+
180
+
181
+ @dataclass(frozen=True)
182
+ class TagAddRequest:
183
+ roar_dir: Path
184
+ cwd: Path
185
+ kv: str # "kind=value"
186
+ target: str
187
+
188
+
189
+ @dataclass(frozen=True)
190
+ class TagRmRequest:
191
+ roar_dir: Path
192
+ cwd: Path
193
+ key_or_kv: str # "kind" or "kind=value"
194
+ target: str
195
+
196
+
197
+ @dataclass(frozen=True)
198
+ class TagShowRequest:
199
+ roar_dir: Path
200
+ cwd: Path
201
+ target: str
202
+
203
+
204
+ @dataclass(frozen=True)
205
+ class TagHistoryRequest:
206
+ roar_dir: Path
207
+ cwd: Path
208
+ target: str
209
+
210
+
211
+ @dataclass(frozen=True)
212
+ class TagBindRequest:
213
+ roar_dir: Path
214
+ cwd: Path
215
+ targets: tuple[str, ...]
216
+
217
+
218
+ @dataclass(frozen=True)
219
+ class TagUnbindRequest:
220
+ roar_dir: Path
221
+ cwd: Path
222
+ targets: tuple[str, ...]
223
+
224
+
225
+ @dataclass(frozen=True)
226
+ class TagWhyRequest:
227
+ roar_dir: Path
228
+ cwd: Path
229
+ target: str
230
+ key: str # "kind" or "kind=value" — value narrows the explanation to one value
@@ -7,6 +7,7 @@ from enum import Enum
7
7
  from typing import TYPE_CHECKING, Any
8
8
 
9
9
  if TYPE_CHECKING:
10
+ from ..tags import WhyNode
10
11
  from .diff_graph import JobMatch, JobNode
11
12
  from .git_readiness import GitReadinessSummary
12
13
 
@@ -146,6 +147,79 @@ class LabelHistorySummary:
146
147
  return "\n\n".join(version.render() for version in self.versions)
147
148
 
148
149
 
150
+ @dataclass(frozen=True)
151
+ class TagBindArtifactSummary:
152
+ """One target's outcome from `roar tag bind`/`unbind` — what the CLI echoes."""
153
+
154
+ display_target: str
155
+ action: str # "bind" | "unbind"
156
+ changed: bool
157
+ promoted: dict[str, list[str]] = field(default_factory=dict)
158
+ size: int | None = None
159
+
160
+ def render(self) -> str:
161
+ verb = "Bound" if self.action == "bind" else "Unbound"
162
+ header = self.display_target
163
+ if self.size is not None:
164
+ header += f" ({self.size} bytes)"
165
+ lines = [f"{verb}: {header}"]
166
+ if self.size == 0:
167
+ lines.append(
168
+ " warning: this is the empty-content hash — shared by every empty "
169
+ "file in every session. Binding it promotes its tags everywhere."
170
+ )
171
+ if not self.changed:
172
+ if self.promoted:
173
+ lines.append(" no change: already up to date")
174
+ else:
175
+ noun = "currently bound" if self.action == "unbind" else "to bind"
176
+ lines.append(f" no change: nothing {noun}")
177
+ return "\n".join(lines)
178
+ for kind in sorted(self.promoted):
179
+ lines.append(f" {kind}={', '.join(self.promoted[kind])}")
180
+ return "\n".join(lines)
181
+
182
+
183
+ @dataclass(frozen=True)
184
+ class TagBindSummary:
185
+ artifacts: list[TagBindArtifactSummary] = field(default_factory=list)
186
+
187
+ def render(self) -> str:
188
+ if not self.artifacts:
189
+ return "No targets."
190
+ return "\n".join(artifact.render() for artifact in self.artifacts)
191
+
192
+
193
+ @dataclass(frozen=True)
194
+ class TagWhySummary:
195
+ """Renders the provenance walk produced by ``roar tag why``.
196
+
197
+ ``roots`` is a forest of ``WhyNode`` (one tree per explained value); each
198
+ node's ``label`` describes one hop back toward a human act (``tag add`` /
199
+ ``run --add-tag`` / a cross-session ``bind``).
200
+ """
201
+
202
+ heading: str
203
+ roots: list[WhyNode] = field(default_factory=list)
204
+ empty_message: str = "(no such tag on target — nothing to explain)"
205
+
206
+ def render(self) -> str:
207
+ lines = [self.heading]
208
+ if not self.roots:
209
+ lines.append(f" {self.empty_message}")
210
+ return "\n".join(lines)
211
+ for root in self.roots:
212
+ lines.extend(self._render_node(root, depth=0))
213
+ return "\n".join(lines)
214
+
215
+ def _render_node(self, node: WhyNode, *, depth: int) -> list[str]:
216
+ indent = " " + " " * depth
217
+ lines = [f"{indent}{'└─ ' if depth else ''}{node.label}"]
218
+ for child in node.children:
219
+ lines.extend(self._render_node(child, depth=depth + 1))
220
+ return lines
221
+
222
+
149
223
  @dataclass(frozen=True)
150
224
  class ShowHashSummary:
151
225
  algorithm: str
@@ -0,0 +1,224 @@
1
+ """Application orchestration for roar tag workflows."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from pathlib import Path
6
+
7
+ from ...core.label_constants import TAG_NAMESPACE
8
+ from ...db.context import create_database_context
9
+ from ..tags import BindResult, TagService, parse_tag_kv, tag_display_pairs
10
+ from .requests import (
11
+ TagAddRequest,
12
+ TagBindRequest,
13
+ TagHistoryRequest,
14
+ TagRmRequest,
15
+ TagShowRequest,
16
+ TagUnbindRequest,
17
+ TagWhyRequest,
18
+ )
19
+ from .results import (
20
+ LabelCurrentSummary,
21
+ LabelEntrySummary,
22
+ LabelHistorySummary,
23
+ LabelHistoryVersionSummary,
24
+ TagBindArtifactSummary,
25
+ TagBindSummary,
26
+ TagWhySummary,
27
+ )
28
+
29
+
30
+ def tag_add(request: TagAddRequest) -> str:
31
+ """Append a value to a tag set and return a rendered summary."""
32
+ return build_tag_add_summary(request).render()
33
+
34
+
35
+ def build_tag_add_summary(request: TagAddRequest) -> LabelCurrentSummary:
36
+ """Build the typed summary for a tag add operation."""
37
+ kind, value = parse_tag_kv(request.kv)
38
+ with create_database_context(request.roar_dir) as db_ctx:
39
+ svc = TagService(db_ctx, request.cwd)
40
+ resolved = svc.resolve_target(request.target)
41
+ changed = svc.add(resolved, kind, value)
42
+ tags = svc.get_tags(resolved)
43
+
44
+ if changed:
45
+ heading = f"Tagged {request.target}: {TAG_NAMESPACE}.{kind} += [{value!r}]"
46
+ else:
47
+ heading = f"No change: {value!r} already present in {TAG_NAMESPACE}.{kind}"
48
+
49
+ return LabelCurrentSummary(
50
+ heading=heading,
51
+ entries=_tag_entries(tags),
52
+ empty_message="(no tags)",
53
+ )
54
+
55
+
56
+ def tag_rm(request: TagRmRequest) -> str:
57
+ """Remove a value (or entire kind) from a tag set and return a rendered summary."""
58
+ return build_tag_rm_summary(request).render()
59
+
60
+
61
+ def build_tag_rm_summary(request: TagRmRequest) -> LabelCurrentSummary:
62
+ """Build the typed summary for a tag rm operation."""
63
+ kind, value = _parse_kind_or_kv(request.key_or_kv)
64
+ with create_database_context(request.roar_dir) as db_ctx:
65
+ svc = TagService(db_ctx, request.cwd)
66
+ resolved = svc.resolve_target(request.target)
67
+ changed = svc.remove(resolved, kind, value)
68
+ tags = svc.get_tags(resolved)
69
+
70
+ if changed:
71
+ if value is not None:
72
+ heading = f"Removed {value!r} from {TAG_NAMESPACE}.{kind} on {request.target}"
73
+ else:
74
+ heading = f"Removed {TAG_NAMESPACE}.{kind} from {request.target}"
75
+ else:
76
+ if value is not None:
77
+ heading = f"No change: {value!r} not found in {TAG_NAMESPACE}.{kind}"
78
+ else:
79
+ heading = f"No change: {TAG_NAMESPACE}.{kind} not present on {request.target}"
80
+
81
+ return LabelCurrentSummary(
82
+ heading=heading,
83
+ entries=_tag_entries(tags),
84
+ empty_message="(no tags remaining)",
85
+ )
86
+
87
+
88
+ def tag_show(request: TagShowRequest) -> str:
89
+ """Show current tags for a target and return a rendered summary."""
90
+ return build_tag_show_summary(request).render()
91
+
92
+
93
+ def build_tag_show_summary(request: TagShowRequest) -> LabelCurrentSummary:
94
+ """Build the typed summary for showing tags."""
95
+ with create_database_context(request.roar_dir) as db_ctx:
96
+ svc = TagService(db_ctx, request.cwd)
97
+ resolved = svc.resolve_target(request.target)
98
+ tags = svc.get_tags(resolved)
99
+
100
+ return LabelCurrentSummary(
101
+ heading=f"Tags on {request.target}:",
102
+ entries=_tag_entries(tags),
103
+ empty_message="(no tags)",
104
+ )
105
+
106
+
107
+ def tag_history(request: TagHistoryRequest) -> str:
108
+ """Show label version history for a target (all keys) and return a rendered summary."""
109
+ return build_tag_history_summary(request).render()
110
+
111
+
112
+ def build_tag_history_summary(request: TagHistoryRequest) -> LabelHistorySummary:
113
+ """Build the typed summary for tag history."""
114
+ with create_database_context(request.roar_dir) as db_ctx:
115
+ svc = TagService(db_ctx, request.cwd)
116
+ resolved = svc.resolve_target(request.target)
117
+ history = svc.history(resolved)
118
+
119
+ return LabelHistorySummary(
120
+ versions=[
121
+ LabelHistoryVersionSummary(
122
+ version=int(row["version"]),
123
+ entries=_tag_entries(row["metadata"].get(TAG_NAMESPACE) or {}),
124
+ )
125
+ for row in history
126
+ if isinstance(row.get("metadata"), dict)
127
+ ]
128
+ )
129
+
130
+
131
+ def tag_why(request: TagWhyRequest) -> str:
132
+ """Explain how a target acquired a tag and return a rendered summary."""
133
+ return build_tag_why_summary(request).render()
134
+
135
+
136
+ def build_tag_why_summary(request: TagWhyRequest) -> TagWhySummary:
137
+ """Build the typed summary for a tag why provenance walk."""
138
+ kind, value = _parse_kind_or_kv(request.key)
139
+ with create_database_context(request.roar_dir) as db_ctx:
140
+ svc = TagService(db_ctx, request.cwd)
141
+ resolved = svc.resolve_target(request.target)
142
+ roots = svc.why(resolved, kind, value)
143
+
144
+ label = f"{kind}={value}" if value is not None else kind
145
+ return TagWhySummary(heading=f"Why does {request.target} have {label}?", roots=roots)
146
+
147
+
148
+ def tag_bind(request: TagBindRequest) -> str:
149
+ """Promote each target's current tags to cross-session scope and return a rendered summary."""
150
+ return build_tag_bind_summary(request).render()
151
+
152
+
153
+ def build_tag_bind_summary(request: TagBindRequest) -> TagBindSummary:
154
+ """Build the typed summary for a tag bind operation."""
155
+ return _build_bind_or_unbind_summary(
156
+ request.roar_dir, request.cwd, request.targets, action="bind"
157
+ )
158
+
159
+
160
+ def tag_unbind(request: TagUnbindRequest) -> str:
161
+ """Revoke each target's currently-bound tags and return a rendered summary."""
162
+ return build_tag_unbind_summary(request).render()
163
+
164
+
165
+ def build_tag_unbind_summary(request: TagUnbindRequest) -> TagBindSummary:
166
+ """Build the typed summary for a tag unbind operation."""
167
+ return _build_bind_or_unbind_summary(
168
+ request.roar_dir, request.cwd, request.targets, action="unbind"
169
+ )
170
+
171
+
172
+ def _build_bind_or_unbind_summary(
173
+ roar_dir: Path, cwd: Path, targets: tuple[str, ...], *, action: str
174
+ ) -> TagBindSummary:
175
+ artifacts: list[TagBindArtifactSummary] = []
176
+ with create_database_context(roar_dir) as db_ctx:
177
+ svc = TagService(db_ctx, cwd)
178
+ for target in targets:
179
+ resolved = svc.resolve_target(target)
180
+ result: BindResult = svc.bind(resolved) if action == "bind" else svc.unbind(resolved)
181
+
182
+ size = None
183
+ if resolved.entity_type == "artifact" and resolved.artifact_id:
184
+ artifact = db_ctx.artifacts.get(resolved.artifact_id)
185
+ if artifact:
186
+ size = artifact.get("size")
187
+
188
+ artifacts.append(
189
+ TagBindArtifactSummary(
190
+ display_target=resolved.display_target or target,
191
+ action=action,
192
+ changed=result.changed,
193
+ promoted=result.promoted,
194
+ size=size,
195
+ )
196
+ )
197
+ return TagBindSummary(artifacts=artifacts)
198
+
199
+
200
+ # ---------------------------------------------------------------------------
201
+ # Helpers
202
+ # ---------------------------------------------------------------------------
203
+
204
+
205
+ def _parse_kind_or_kv(key_or_kv: str) -> tuple[str, str | None]:
206
+ """Parse ``kind`` or ``kind=value``. Returns (kind, value_or_None)."""
207
+ if "=" in key_or_kv:
208
+ kind, value = parse_tag_kv(key_or_kv)
209
+ return kind, value
210
+ kind = key_or_kv.strip()
211
+ if not kind:
212
+ raise ValueError("Kind cannot be empty.")
213
+ return kind, None
214
+
215
+
216
+ def _tag_entries(tags: dict) -> list[LabelEntrySummary]:
217
+ """Convert a tag.* subtree to display entries via the shared renderer.
218
+
219
+ Uses ``tag_display_pairs`` so ``roar tag show`` and ``roar show`` render tags
220
+ identically (values only; skips the bind ledger).
221
+ """
222
+ return [
223
+ LabelEntrySummary(key=kind, display_value=value) for kind, value in tag_display_pairs(tags)
224
+ ]
@@ -190,6 +190,8 @@ def execute_and_report(
190
190
  config_start_dir: str | Path | None = None,
191
191
  tracer_mode: str | None = None,
192
192
  tracer_fallback: bool | None = None,
193
+ block_tags: list[str] | None = None,
194
+ add_tags: list[str] | None = None,
193
195
  ) -> ExecutionReport:
194
196
  """Execute command via selected backend and show the run report."""
195
197
  hash_algos = cast(list[Literal["blake3", "sha256", "sha512", "md5"]], hash_algorithms)
@@ -210,6 +212,8 @@ def execute_and_report(
210
212
  hash_algorithms=hash_algos,
211
213
  tracer_mode=tracer_mode, # type: ignore[arg-type]
212
214
  tracer_fallback=tracer_fallback,
215
+ block_tags=block_tags or [],
216
+ add_tags=add_tags or [],
213
217
  )
214
218
 
215
219
  backend = get_execution_backend(backend_name)
@@ -17,6 +17,8 @@ class RunRequest:
17
17
  tracer_mode: str | None = None
18
18
  tracer_fallback: bool | None = None
19
19
  hash_algorithms: tuple[str, ...] = field(default_factory=tuple)
20
+ block_tags: tuple[str, ...] = field(default_factory=tuple)
21
+ add_tags: tuple[str, ...] = field(default_factory=tuple)
20
22
 
21
23
 
22
24
  @dataclass(frozen=True)