roar-cli 0.4.0__tar.gz → 0.4.2__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.
- {roar_cli-0.4.0 → roar_cli-0.4.2}/PKG-INFO +2 -1
- {roar_cli-0.4.0 → roar_cli-0.4.2}/pyproject.toml +3 -1
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/analyzers/experiment_trackers.py +103 -3
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/get/requests.py +1 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/get/service.py +105 -16
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/publish/put_execution.py +51 -5
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/publish/put_preparation.py +3 -1
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/publish/registration.py +28 -8
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/publish/registration_package.py +34 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/publish/service.py +12 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/reproduce/requests.py +5 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/reproduce/service.py +127 -1
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/reproducibility/report.py +18 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/run/execution.py +26 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/run/service.py +5 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/system_labels.py +4 -0
- roar_cli-0.4.2/roar/backends/k8s/attach.py +402 -0
- roar_cli-0.4.2/roar/backends/k8s/bundles.py +135 -0
- roar_cli-0.4.2/roar/backends/k8s/config.py +194 -0
- roar_cli-0.4.2/roar/backends/k8s/fragment_reconstituter.py +261 -0
- roar_cli-0.4.2/roar/backends/k8s/host_execution.py +196 -0
- roar_cli-0.4.2/roar/backends/k8s/lineage.py +144 -0
- roar_cli-0.4.2/roar/backends/k8s/manifest.py +756 -0
- roar_cli-0.4.2/roar/backends/k8s/mount_map.py +182 -0
- roar_cli-0.4.2/roar/backends/k8s/object_io.py +220 -0
- roar_cli-0.4.2/roar/backends/k8s/plugin.py +114 -0
- roar_cli-0.4.2/roar/backends/k8s/pod_entry.py +366 -0
- roar_cli-0.4.2/roar/backends/k8s/rayjob.py +230 -0
- roar_cli-0.4.2/roar/backends/k8s/secret_cleanup.py +105 -0
- roar_cli-0.4.2/roar/backends/k8s/submit.py +440 -0
- roar_cli-0.4.2/roar/backends/k8s/webhook.py +313 -0
- roar_cli-0.4.2/roar/backends/k8s/workload_wait.py +133 -0
- roar_cli-0.4.2/roar/backends/osmo/export.py +48 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/backends/ray/fragment_reconstituter.py +22 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/backends/ray/roar_worker.py +86 -33
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/backends/ray/runtime_hooks.py +67 -3
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/backends/ray/submit.py +2 -1
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/command_registry.py +3 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/commands/get.py +11 -0
- roar_cli-0.4.2/roar/cli/commands/k8s.py +226 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/commands/proxy.py +7 -3
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/commands/put.py +14 -2
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/commands/register.py +98 -31
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/commands/reproduce.py +16 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/commands/scope.py +16 -6
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/context.py +15 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/publish_intent.py +5 -0
- roar_cli-0.4.2/roar/cli/templates/agents/SKILL.md.tmpl +198 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/templates/agents/agents_section.md.tmpl +3 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/core/models/provenance.py +4 -0
- {roar_cli-0.4.0/roar/backends/osmo → roar_cli-0.4.2/roar/execution/fragments}/export.py +32 -13
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/fragments/lineage.py +12 -6
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/fragments/models.py +18 -0
- roar_cli-0.4.2/roar/execution/fragments/sessions.py +83 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/fragments/transport.py +19 -2
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/framework/registry.py +63 -2
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/provenance/assembler.py +5 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/provenance/runtime_collector.py +74 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/runtime/proxy_resource.py +22 -2
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/runtime/tracer.py +1 -1
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/runtime/worker_bootstrap.py +22 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/download/hf.py +9 -3
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/glaas/__init__.py +1 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/glaas/client.py +5 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/glaas/fragment_streamer.py +66 -3
- roar_cli-0.4.2/roar/integrations/storage/hf.py +146 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/storage/publish.py +5 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/presenters/show_renderer.py +8 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/publish_auth.py +71 -5
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/scope_config.py +4 -0
- roar_cli-0.4.2/roar/tui/screens/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/services/proxy/src/main.rs +12 -0
- roar_cli-0.4.0/roar/cli/templates/agents/SKILL.md.tmpl +0 -123
- roar_cli-0.4.0/roar/execution/fragments/sessions.py +0 -38
- {roar_cli-0.4.0 → roar_cli-0.4.2}/LICENSE +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/README.md +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/__main__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/analyzers/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/analyzers/base.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/composite/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/composite/canonical.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/composite/detect.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/composite/qualifying.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/get/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/get/results.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/get/transfer.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/git.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/label_rendering.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/labels.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/lookup/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/lookup/models.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/lookup/policy.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/lookup/refs.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/lookup/remote_artifacts.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/lookup/runner.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/publish/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/publish/anchor_attribution.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/publish/blake3_upgrade.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/publish/collection.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/publish/composite_builder.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/publish/composites.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/publish/datasets.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/publish/form_composites.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/publish/git_remote.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/publish/job_links.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/publish/job_preparation.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/publish/lineage.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/publish/lineage_composite_formation.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/publish/lineage_composites.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/publish/metadata.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/publish/put_composites.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/publish/register_execution.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/publish/register_preparation.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/publish/register_preview_jobs.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/publish/register_tag_push.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/publish/remote_job_uids.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/publish/remote_registry.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/publish/requests.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/publish/results.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/publish/runtime.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/publish/secrets.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/publish/session.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/publish/source_resolution.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/publish/targets.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/publish/view_edges.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/query/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/query/dag.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/query/db_status.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/query/diff.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/query/diff_engine.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/query/diff_graph.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/query/diff_refs.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/query/git_readiness.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/query/inputs.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/query/label.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/query/lineage.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/query/log.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/query/requests.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/query/results.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/query/show.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/query/status.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/query/tag.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/reproduce/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/reproduce/environment.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/reproduce/lookup.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/reproduce/results.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/reproducibility/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/run/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/run/dag_references.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/run/dirty_tree_classify.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/run/dirty_tree_error.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/run/gitignore_suggest.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/run/output_followup.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/run/requests.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/run/verbosity.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/tags.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/workflow/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/workflow/requests.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/workflow/results.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/application/workflow/service.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/auth_store.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/backends/__init__.py +0 -0
- {roar_cli-0.4.0/roar/tui/screens → roar_cli-0.4.2/roar/backends/k8s}/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/backends/local/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/backends/local/plugin.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/backends/osmo/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/backends/osmo/config.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/backends/osmo/host_execution.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/backends/osmo/lineage.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/backends/osmo/plugin.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/backends/osmo/runtime_bundle.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/backends/osmo/submit.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/backends/osmo/workflow.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/backends/ray/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/backends/ray/_agent_names.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/backends/ray/collector.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/backends/ray/config.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/backends/ray/constants.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/backends/ray/env_contract.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/backends/ray/fragment.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/backends/ray/node_agent.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/backends/ray/plugin.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/backends/ray/proxy_fragments.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/backends/ray/s3_key_paths.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/backends/ray/submit_context.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/_format.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/_tag_kinds.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/commands/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/commands/auth.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/commands/build.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/commands/config.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/commands/dag.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/commands/db.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/commands/diff.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/commands/env.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/commands/export_registration_package.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/commands/filter.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/commands/init.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/commands/init_agents.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/commands/inputs.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/commands/label.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/commands/lineage.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/commands/log.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/commands/login.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/commands/logout.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/commands/osmo.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/commands/pop.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/commands/projects.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/commands/reset.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/commands/run.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/commands/session.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/commands/show.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/commands/status.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/commands/tag.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/commands/telemetry.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/commands/tracer.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/commands/tui.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/commands/whoami.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/commands/workflow.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/cli/decorators.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/core/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/core/bootstrap.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/core/canonical_session.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/core/digests.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/core/dto/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/core/dto/registration.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/core/exceptions.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/core/interfaces/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/core/interfaces/config.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/core/interfaces/lineage.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/core/interfaces/logger.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/core/interfaces/presenter.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/core/interfaces/provenance.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/core/interfaces/registration.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/core/interfaces/repositories.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/core/interfaces/reproduction.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/core/interfaces/run.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/core/interfaces/services.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/core/interfaces/telemetry.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/core/interfaces/vcs.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/core/label_constants.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/core/label_origins.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/core/logging.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/core/models/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/core/models/artifact.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/core/models/base.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/core/models/dag.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/core/models/dataset_identifier.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/core/models/glaas.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/core/models/job.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/core/models/lineage.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/core/models/run.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/core/models/session.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/core/models/telemetry.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/core/models/vcs.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/core/operation_metadata.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/core/session_hash.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/core/step_name.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/core/tracer_modes.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/core/validation.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/db/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/db/context.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/db/engine.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/db/hashing/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/db/hashing/backend.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/db/hashing/blake3.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/db/models.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/db/query_context.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/db/repositories/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/db/repositories/artifact.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/db/repositories/collection.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/db/repositories/composite.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/db/repositories/hash_cache.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/db/repositories/job.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/db/repositories/label.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/db/repositories/session.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/db/schema.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/db/services/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/db/services/hashing.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/db/services/job_recording.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/db/services/lineage.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/db/services/session.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/db/step_priority.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/cluster/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/cluster/bridge.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/cluster/proxy.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/cluster/proxy_config.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/fragments/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/fragments/reconstitution.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/framework/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/framework/contract.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/framework/planning.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/framework/runtime_imports.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/provenance/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/provenance/build_pip_collector.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/provenance/build_tool_collector.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/provenance/data_loader.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/provenance/file_filter.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/provenance/package_collector.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/provenance/process_summarizer.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/provenance/service.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/recording/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/recording/dataset_identifier.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/recording/dataset_metadata.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/recording/dataset_profile.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/recording/job_recording.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/reproduction/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/reproduction/environment_setup.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/reproduction/installers.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/reproduction/pipeline_executor.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/reproduction/pipeline_metadata.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/runtime/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/runtime/abi_probe.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/runtime/active_runs.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/runtime/backup.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/runtime/coordinator.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/runtime/driver_entrypoint.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/runtime/errors.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/runtime/host_execution.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/runtime/inject/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/runtime/inject/sitecustomize.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/runtime/inject/support.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/runtime/inject/tracker.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/runtime/lazy_install.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/runtime/resources.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/runtime/signal_handler.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/runtime/tracer_backends.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/execution/runtime/tracer_banner.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/filters/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/filters/files.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/filters/omit.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/glaas_auth.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/glaas_client.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/bootstrap.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/config/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/config/access.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/config/loader.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/config/raw.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/config/schema.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/discovery.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/download/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/download/base.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/download/gcs.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/download/get.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/download/http.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/download/noop.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/download/s3.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/git/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/git/base.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/git/context.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/git/provider.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/glaas/auth.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/glaas/registration/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/glaas/registration/_artifact_ref.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/glaas/registration/artifact.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/glaas/registration/coordinator.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/glaas/registration/job.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/glaas/registration/session.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/glaas/transport.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/registry.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/resolution.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/storage/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/storage/base.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/storage/gcs.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/storage/memory.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/storage/noop.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/storage/s3.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/telemetry/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/telemetry/base.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/integrations/telemetry/wandb.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/presenters/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/presenters/console.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/presenters/dag_data_builder.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/presenters/dag_renderer.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/presenters/diff_renderer.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/presenters/formatting.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/presenters/null.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/presenters/run_report.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/presenters/spinner.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/presenters/terminal.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/require.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/telemetry/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/telemetry/_io.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/telemetry/capabilities.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/telemetry/config.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/telemetry/hooks.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/telemetry/install.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/telemetry/paths.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/telemetry/payload.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/telemetry/queue.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/telemetry/stats.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/telemetry/uploader.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/tui/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/tui/app.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/tui/data.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/tui/screens/config_editor.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/tui/screens/label_editor.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/tui/screens/launcher.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/tui/screens/log.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/tui/screens/main.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/tui/screens/search.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/tui/screens/session_picker.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/tui/tmux.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/tui/widgets/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/tui/widgets/detail.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/utils/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/utils/cloud.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/utils/git_url.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/roar/version_check.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/Cargo.lock +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/Cargo.toml +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/crates/artifact-hash-core/Cargo.toml +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/crates/artifact-hash-core/src/lib.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/crates/artifact-hash-py/Cargo.toml +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/crates/artifact-hash-py/src/lib.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/crates/tracer-fd/Cargo.toml +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/crates/tracer-fd/src/lib.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/crates/tracer-runtime/Cargo.toml +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/crates/tracer-runtime/src/lib.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/crates/tracer-schema/Cargo.toml +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/crates/tracer-schema/src/lib.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/services/proxy/Cargo.lock +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/services/proxy/Cargo.toml +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/services/proxy/src/forward.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/services/proxy/src/s3.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/tracers/ebpf/common/Cargo.toml +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/tracers/ebpf/common/src/lib.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/tracers/ebpf/probe/Cargo.toml +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/tracers/ebpf/probe/rust-toolchain.toml +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/tracers/ebpf/probe/src/main.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/tracers/ebpf/userspace/Cargo.toml +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/tracers/ebpf/userspace/build.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/tracers/ebpf/userspace/src/attach.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/tracers/ebpf/userspace/src/bin/roard.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/tracers/ebpf/userspace/src/client.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/tracers/ebpf/userspace/src/daemon.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/tracers/ebpf/userspace/src/events.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/tracers/ebpf/userspace/src/ipc.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/tracers/ebpf/userspace/src/lib.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/tracers/ebpf/userspace/src/main.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/tracers/ebpf/userspace/src/state.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/tracers/preload/Cargo.toml +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/tracers/preload/build.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/tracers/preload/src/bin/io_fixture.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/tracers/preload/src/interpose.c +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/tracers/preload/src/ipc.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/tracers/preload/src/lib.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/tracers/preload/src/main.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/tracers/preload/tests/comprehensive.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/tracers/preload/tests/standalone.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/tracers/ptrace/Cargo.toml +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/tracers/ptrace/rustfmt.toml +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/tracers/ptrace/src/arch.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/tracers/ptrace/src/main.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/rust/tracers/ptrace/src/seccomp.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.2}/scripts/sync_packaged_rust_artifacts.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: roar-cli
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.2
|
|
4
4
|
Classifier: Development Status :: 3 - Alpha
|
|
5
5
|
Classifier: Intended Audience :: Developers
|
|
6
6
|
Classifier: Intended Audience :: Science/Research
|
|
@@ -34,6 +34,7 @@ Requires-Dist: ruff>=0.8.0 ; extra == 'dev'
|
|
|
34
34
|
Requires-Dist: mypy>=1.13.0 ; extra == 'dev'
|
|
35
35
|
Requires-Dist: boto3>=1.28.0 ; extra == 'dev'
|
|
36
36
|
Requires-Dist: google-cloud-storage>=2.10.0 ; extra == 'dev'
|
|
37
|
+
Requires-Dist: huggingface-hub>=0.20.0 ; extra == 'dev'
|
|
37
38
|
Provides-Extra: dev
|
|
38
39
|
License-File: LICENSE
|
|
39
40
|
Summary: Reproducibility and provenance tracker for ML training pipelines
|
|
@@ -5,7 +5,7 @@ build-backend = "maturin"
|
|
|
5
5
|
|
|
6
6
|
[project]
|
|
7
7
|
name = "roar-cli"
|
|
8
|
-
version = "0.4.
|
|
8
|
+
version = "0.4.2"
|
|
9
9
|
description = "Reproducibility and provenance tracker for ML training pipelines"
|
|
10
10
|
authors = [
|
|
11
11
|
{ name="TReqs Team", email="info@treqs.ai" }
|
|
@@ -68,6 +68,7 @@ dev = [
|
|
|
68
68
|
"mypy>=1.13.0",
|
|
69
69
|
"boto3>=1.28.0",
|
|
70
70
|
"google-cloud-storage>=2.10.0",
|
|
71
|
+
"huggingface_hub>=0.20.0",
|
|
71
72
|
]
|
|
72
73
|
|
|
73
74
|
[project.scripts]
|
|
@@ -123,6 +124,7 @@ markers = [
|
|
|
123
124
|
"diagnostic: Opt-in diagnostics or aspirational performance budgets outside the default gate",
|
|
124
125
|
"large_pipeline: Stress-style pipeline coverage with larger DAG fixtures",
|
|
125
126
|
"osmo_e2e: OSMO end-to-end tests requiring a Docker Compose managed KIND harness",
|
|
127
|
+
"k8s_e2e: Kubernetes end-to-end tests requiring the KIND harness (tests/backends/k8s)",
|
|
126
128
|
"ray_e2e: Ray end-to-end tests requiring a running Docker cluster",
|
|
127
129
|
"ray_contract: User-facing Ray contract tests using `roar run ray job submit ...`",
|
|
128
130
|
"ray_diagnostic: Diagnostic Ray tests that intentionally inspect internal runtime details",
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
4
|
import re
|
|
5
|
+
import sqlite3
|
|
5
6
|
from pathlib import Path
|
|
6
7
|
from typing import Any, ClassVar
|
|
7
8
|
|
|
@@ -18,6 +19,7 @@ class ExperimentTrackerAnalyzer(Analyzer):
|
|
|
18
19
|
TRACKER_PATTERNS: ClassVar[dict[str, list[str]]] = {
|
|
19
20
|
"wandb": ["wandb/", ".wandb"],
|
|
20
21
|
"mlflow": ["mlruns/", "mlartifacts/"],
|
|
22
|
+
"trackio": ["huggingface/trackio", "/trackio/"],
|
|
21
23
|
"neptune": [".neptune/"],
|
|
22
24
|
"tensorboard": ["/runs/", "events.out.tfevents"],
|
|
23
25
|
}
|
|
@@ -72,7 +74,12 @@ class ExperimentTrackerAnalyzer(Analyzer):
|
|
|
72
74
|
for tracker in trackers_found:
|
|
73
75
|
run_info = self._extract_run_info(tracker, written, env)
|
|
74
76
|
if run_info:
|
|
75
|
-
|
|
77
|
+
# trackio reports one run per project DB (a run may touch
|
|
78
|
+
# several); the other trackers return a single run dict.
|
|
79
|
+
if isinstance(run_info, list):
|
|
80
|
+
results["runs"].extend(run_info)
|
|
81
|
+
else:
|
|
82
|
+
results["runs"].append(run_info)
|
|
76
83
|
|
|
77
84
|
# Add ignore patterns for this tracker
|
|
78
85
|
for pattern in self.IGNORE_PATTERNS:
|
|
@@ -88,18 +95,26 @@ class ExperimentTrackerAnalyzer(Analyzer):
|
|
|
88
95
|
results["ignore_patterns"].extend(["mlruns/*", "mlartifacts/*"])
|
|
89
96
|
if "neptune" in trackers_found:
|
|
90
97
|
results["ignore_patterns"].append(".neptune/*")
|
|
98
|
+
if "trackio" in trackers_found:
|
|
99
|
+
results["ignore_patterns"].append("*/trackio/*")
|
|
91
100
|
|
|
92
101
|
# Dedupe
|
|
93
102
|
results["ignore_patterns"] = sorted(set(results["ignore_patterns"]))
|
|
94
103
|
|
|
95
104
|
return results if results["trackers_detected"] else None
|
|
96
105
|
|
|
97
|
-
def _extract_run_info(self, tracker: str, written_files: list, env: dict) -> dict | None:
|
|
98
|
-
"""Extract run URL and metadata for a specific tracker.
|
|
106
|
+
def _extract_run_info(self, tracker: str, written_files: list, env: dict) -> dict | list | None:
|
|
107
|
+
"""Extract run URL and metadata for a specific tracker.
|
|
108
|
+
|
|
109
|
+
Most trackers return a single run dict; ``trackio`` returns a list of
|
|
110
|
+
per-project run dicts (or ``None`` when nothing usable was found).
|
|
111
|
+
"""
|
|
99
112
|
if tracker == "wandb":
|
|
100
113
|
return self._extract_wandb_info(written_files, env)
|
|
101
114
|
elif tracker == "mlflow":
|
|
102
115
|
return self._extract_mlflow_info(written_files, env)
|
|
116
|
+
elif tracker == "trackio":
|
|
117
|
+
return self._extract_trackio_info(written_files, env)
|
|
103
118
|
elif tracker == "neptune":
|
|
104
119
|
return self._extract_neptune_info(written_files, env)
|
|
105
120
|
return None
|
|
@@ -198,6 +213,91 @@ class ExperimentTrackerAnalyzer(Analyzer):
|
|
|
198
213
|
|
|
199
214
|
return info if len(info) > 1 else None
|
|
200
215
|
|
|
216
|
+
def _extract_trackio_info(self, written_files: list, env: dict) -> list | None:
|
|
217
|
+
"""Extract trackio run info + the hosted-dashboard URL — scrape only.
|
|
218
|
+
|
|
219
|
+
trackio stores one SQLite DB per project at ``.../huggingface/trackio/
|
|
220
|
+
<project>.db`` and, when a run syncs to a HF Space, records the Space in
|
|
221
|
+
``project_metadata`` (``key='space_id'``). We read that link + the run
|
|
222
|
+
identity, exactly as the W&B extractor reads wandb's on-disk run URL — no
|
|
223
|
+
roar-side config, no env, and **never the metrics**: TReqs stores no
|
|
224
|
+
customer data, so the DAG carries a link to the externally-hosted
|
|
225
|
+
experiment, and the metrics live on the dashboard.
|
|
226
|
+
|
|
227
|
+
Returns ONE record per project DB (never splicing one project's identity
|
|
228
|
+
onto another's Space), or ``None`` if no DB yielded anything usable. Each
|
|
229
|
+
record's URL is ``https://huggingface.co/spaces/<space_id>?project=<project>``.
|
|
230
|
+
(``env`` is unused — the space comes from what trackio itself persisted.)
|
|
231
|
+
"""
|
|
232
|
+
del env
|
|
233
|
+
db_paths = sorted({p for p in written_files if "trackio/" in p and p.endswith(".db")})
|
|
234
|
+
|
|
235
|
+
runs: list[dict[str, Any]] = []
|
|
236
|
+
for db_path in db_paths:
|
|
237
|
+
path = Path(db_path)
|
|
238
|
+
if not path.exists():
|
|
239
|
+
continue
|
|
240
|
+
info: dict[str, Any] = {"tracker": "trackio", "project": path.stem}
|
|
241
|
+
try:
|
|
242
|
+
con = sqlite3.connect(f"file:{db_path}?mode=ro", uri=True)
|
|
243
|
+
except sqlite3.Error:
|
|
244
|
+
continue
|
|
245
|
+
try:
|
|
246
|
+
# Two INDEPENDENT lookups: an older/imported trackio schema may
|
|
247
|
+
# lack a ``run_id`` column or the ``project_metadata`` table, so
|
|
248
|
+
# a failure of one must not discard the other.
|
|
249
|
+
run = self._trackio_run_identity(con)
|
|
250
|
+
space = self._trackio_space_id(con)
|
|
251
|
+
finally:
|
|
252
|
+
con.close()
|
|
253
|
+
|
|
254
|
+
if run:
|
|
255
|
+
info["run_id"], info["run_name"] = run
|
|
256
|
+
if space:
|
|
257
|
+
info["space_id"] = space
|
|
258
|
+
info["url"] = f"https://huggingface.co/spaces/{space}?project={info['project']}"
|
|
259
|
+
|
|
260
|
+
# Keep only DBs that yielded a run identity and/or a hosted Space
|
|
261
|
+
# (more than the always-present tracker+project keys).
|
|
262
|
+
if len(info) > 2:
|
|
263
|
+
runs.append(info)
|
|
264
|
+
|
|
265
|
+
return runs or None
|
|
266
|
+
|
|
267
|
+
@staticmethod
|
|
268
|
+
def _trackio_run_identity(con: "sqlite3.Connection") -> tuple | None:
|
|
269
|
+
"""``(run_id, run_name)`` of the most recent metric row, tolerating
|
|
270
|
+
older schemas whose ``metrics`` table lacks a ``run_id`` column (trackio
|
|
271
|
+
produces these when importing TensorBoard/older runs)."""
|
|
272
|
+
try:
|
|
273
|
+
cols = {row[1] for row in con.execute("PRAGMA table_info(metrics)").fetchall()}
|
|
274
|
+
except sqlite3.Error:
|
|
275
|
+
return None
|
|
276
|
+
if not cols or not ({"run_id", "run_name"} & cols):
|
|
277
|
+
return None
|
|
278
|
+
run_id_expr = "run_id" if "run_id" in cols else "NULL"
|
|
279
|
+
run_name_expr = "run_name" if "run_name" in cols else "NULL"
|
|
280
|
+
try:
|
|
281
|
+
row = con.execute(
|
|
282
|
+
f"SELECT {run_id_expr}, {run_name_expr} FROM metrics ORDER BY rowid DESC LIMIT 1"
|
|
283
|
+
).fetchone()
|
|
284
|
+
except sqlite3.Error:
|
|
285
|
+
return None
|
|
286
|
+
if not row or (row[0] is None and row[1] is None):
|
|
287
|
+
return None
|
|
288
|
+
return row[0], row[1]
|
|
289
|
+
|
|
290
|
+
@staticmethod
|
|
291
|
+
def _trackio_space_id(con: "sqlite3.Connection") -> str | None:
|
|
292
|
+
"""The hosted HF Space id trackio persisted once a run synced, or None."""
|
|
293
|
+
try:
|
|
294
|
+
row = con.execute(
|
|
295
|
+
"SELECT value FROM project_metadata WHERE key = 'space_id' LIMIT 1"
|
|
296
|
+
).fetchone()
|
|
297
|
+
except sqlite3.Error:
|
|
298
|
+
return None
|
|
299
|
+
return row[0] if row and row[0] else None
|
|
300
|
+
|
|
201
301
|
def _extract_mlflow_info(self, written_files: list, env: dict) -> dict | None:
|
|
202
302
|
"""Extract MLflow run info from local files."""
|
|
203
303
|
info = {"tracker": "mlflow"}
|
|
@@ -23,3 +23,4 @@ class GetRequest:
|
|
|
23
23
|
step_name: str | None = None
|
|
24
24
|
limit: int | None = None # download only the first N data files (subset get)
|
|
25
25
|
full_anchor: bool = False # re-hash non-LFS identity files past the budget
|
|
26
|
+
cache: str | None = None # fetch bytes from this mirror; record `source` as canonical
|
|
@@ -12,6 +12,7 @@ from ...core.operation_metadata import build_operation_metadata_json
|
|
|
12
12
|
from ...db.context import create_database_context
|
|
13
13
|
from ...execution.recording import LocalJobRecorder, LocalRecordedArtifact
|
|
14
14
|
from ...integrations.download import parse_source, resolve_download_backend
|
|
15
|
+
from ...integrations.download.base import DownloadError
|
|
15
16
|
from .requests import GetRequest
|
|
16
17
|
from .results import GetDownloadedFile, GetResponse
|
|
17
18
|
from .transfer import GetService, GetTransferResult
|
|
@@ -22,10 +23,27 @@ def get_artifacts(request: GetRequest) -> GetResponse:
|
|
|
22
23
|
bootstrap(request.roar_dir)
|
|
23
24
|
logger = get_logger()
|
|
24
25
|
|
|
25
|
-
parsed_source = parse_source(request.source)
|
|
26
|
-
|
|
26
|
+
parsed_source = parse_source(request.source) # canonical — always what we RECORD
|
|
27
|
+
# Fetch location: the mirror (`--cache`) when given, else the canonical source.
|
|
28
|
+
# Recording below always uses the canonical `parsed_source`, so the artifact's
|
|
29
|
+
# source_url / the AI-BOM downloadLocation stay the public URL, not the mirror.
|
|
30
|
+
fetch_url = request.cache or request.source
|
|
31
|
+
backend = resolve_download_backend(fetch_url)
|
|
32
|
+
fetch_parsed = parse_source(fetch_url)
|
|
27
33
|
repo_root = request.repo_root or request.cwd
|
|
28
|
-
is_prefix =
|
|
34
|
+
is_prefix = fetch_url.rstrip("/") != fetch_url or fetch_parsed.is_prefix
|
|
35
|
+
|
|
36
|
+
# A `--cache` mirror is only integrity-bound to the canonical identity when a
|
|
37
|
+
# `--hash` is given. Without it, the mirror's bytes are recorded under the
|
|
38
|
+
# canonical source_url unverified — warn so provenance isn't silently trusted.
|
|
39
|
+
if request.cache and not request.expected_hash:
|
|
40
|
+
logger.warning(
|
|
41
|
+
"--cache %s used without --hash: the mirror's bytes are not integrity-checked "
|
|
42
|
+
"against the canonical source %s, yet are recorded under it. Pass --hash "
|
|
43
|
+
"<digest> to bind the download to a known hash.",
|
|
44
|
+
request.cache,
|
|
45
|
+
request.source,
|
|
46
|
+
)
|
|
29
47
|
|
|
30
48
|
git_commit = None
|
|
31
49
|
git_branch = None
|
|
@@ -88,20 +106,57 @@ def get_artifacts(request: GetRequest) -> GetResponse:
|
|
|
88
106
|
pass
|
|
89
107
|
|
|
90
108
|
with create_database_context(request.roar_dir) as db_ctx:
|
|
91
|
-
service = GetService(
|
|
92
|
-
backend=backend,
|
|
93
|
-
source=parsed_source,
|
|
94
|
-
repo_root=repo_root,
|
|
95
|
-
)
|
|
96
109
|
t0 = time.time()
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
110
|
+
fetched_from_cache = False
|
|
111
|
+
try:
|
|
112
|
+
transfer_result = GetService(
|
|
113
|
+
backend=backend,
|
|
114
|
+
source=fetch_parsed,
|
|
115
|
+
repo_root=repo_root,
|
|
116
|
+
).get(
|
|
117
|
+
destination=request.destination,
|
|
118
|
+
expected_hash=request.expected_hash,
|
|
119
|
+
dry_run=request.dry_run,
|
|
120
|
+
force=request.force,
|
|
121
|
+
is_prefix=is_prefix,
|
|
122
|
+
limit=request.limit,
|
|
123
|
+
)
|
|
124
|
+
fetched_from_cache = bool(request.cache)
|
|
125
|
+
# The transfer layer REPORTS a hash mismatch (and other soft failures)
|
|
126
|
+
# as success=False rather than raising, so trigger the same cache
|
|
127
|
+
# fallback here — otherwise a corrupt mirror hard-fails the whole get
|
|
128
|
+
# even when the canonical source would succeed (the documented behavior).
|
|
129
|
+
if request.cache and not transfer_result.dry_run and not transfer_result.success:
|
|
130
|
+
raise DownloadError(transfer_result.error or "cache fetch was unsuccessful")
|
|
131
|
+
except (DownloadError, FileNotFoundError, ValueError, OSError) as exc:
|
|
132
|
+
# A `--cache` mirror is best-effort: on miss / unreachable / hash
|
|
133
|
+
# mismatch, fall back to the canonical source (still hash-verified via
|
|
134
|
+
# --hash if given, and by content-addressing at reproduce time). A get
|
|
135
|
+
# without a cache re-raises unchanged.
|
|
136
|
+
if not request.cache:
|
|
137
|
+
raise
|
|
138
|
+
logger.warning(
|
|
139
|
+
"cache fetch from %s failed (%s); falling back to canonical source %s",
|
|
140
|
+
request.cache,
|
|
141
|
+
exc,
|
|
142
|
+
request.source,
|
|
143
|
+
)
|
|
144
|
+
fetched_from_cache = False
|
|
145
|
+
canonical_is_prefix = (
|
|
146
|
+
request.source.rstrip("/") != request.source or parsed_source.is_prefix
|
|
147
|
+
)
|
|
148
|
+
transfer_result = GetService(
|
|
149
|
+
backend=resolve_download_backend(request.source),
|
|
150
|
+
source=parsed_source,
|
|
151
|
+
repo_root=repo_root,
|
|
152
|
+
).get(
|
|
153
|
+
destination=request.destination,
|
|
154
|
+
expected_hash=request.expected_hash,
|
|
155
|
+
dry_run=request.dry_run,
|
|
156
|
+
force=request.force,
|
|
157
|
+
is_prefix=canonical_is_prefix,
|
|
158
|
+
limit=request.limit,
|
|
159
|
+
)
|
|
105
160
|
download_duration = time.time() - t0
|
|
106
161
|
|
|
107
162
|
result = _materialize_get_result(
|
|
@@ -114,6 +169,8 @@ def get_artifacts(request: GetRequest) -> GetResponse:
|
|
|
114
169
|
git_repo=git_repo_url,
|
|
115
170
|
duration_seconds=download_duration,
|
|
116
171
|
backend=backend,
|
|
172
|
+
fetched_from_cache=fetched_from_cache,
|
|
173
|
+
fetch_url=fetch_url,
|
|
117
174
|
)
|
|
118
175
|
|
|
119
176
|
git_tag_name = None
|
|
@@ -145,6 +202,26 @@ def get_artifacts(request: GetRequest) -> GetResponse:
|
|
|
145
202
|
)
|
|
146
203
|
|
|
147
204
|
|
|
205
|
+
def _canonical_source_url(file_info, request: GetRequest, fetch_url, fetched_from_cache: bool):
|
|
206
|
+
"""The canonical (recorded) URL for one downloaded file.
|
|
207
|
+
|
|
208
|
+
When the bytes came from the canonical source (no ``--cache``, or a cache
|
|
209
|
+
miss/mismatch that fell back), each file's own fetch URL is already canonical.
|
|
210
|
+
When they came from a ``--cache`` mirror, remap each file's mirror URL back
|
|
211
|
+
onto the canonical prefix, so a PREFIX get records each file's own canonical
|
|
212
|
+
object (``s3://canon/data/a.pt``) rather than the bare prefix for every file.
|
|
213
|
+
"""
|
|
214
|
+
remote_url = file_info.remote_url or ""
|
|
215
|
+
if not fetched_from_cache:
|
|
216
|
+
return remote_url or request.source
|
|
217
|
+
# Fetched from the mirror: swap the mirror prefix for the canonical one.
|
|
218
|
+
if fetch_url and remote_url.startswith(fetch_url) and remote_url != fetch_url:
|
|
219
|
+
suffix = remote_url[len(fetch_url) :]
|
|
220
|
+
return request.source.rstrip("/") + "/" + suffix.lstrip("/")
|
|
221
|
+
# Single-file cache (or an unmappable URL): the file itself IS the canonical source.
|
|
222
|
+
return request.source
|
|
223
|
+
|
|
224
|
+
|
|
148
225
|
def _materialize_get_result(
|
|
149
226
|
*,
|
|
150
227
|
db_ctx,
|
|
@@ -156,6 +233,8 @@ def _materialize_get_result(
|
|
|
156
233
|
git_repo: str | None = None,
|
|
157
234
|
duration_seconds: float = 0.0,
|
|
158
235
|
backend=None,
|
|
236
|
+
fetched_from_cache: bool = False,
|
|
237
|
+
fetch_url: str | None = None,
|
|
159
238
|
) -> GetResponse:
|
|
160
239
|
if transfer_result.dry_run or not transfer_result.success:
|
|
161
240
|
return GetResponse(
|
|
@@ -204,11 +283,18 @@ def _materialize_get_result(
|
|
|
204
283
|
# downloaded files are the composite's components.
|
|
205
284
|
output_artifacts: list[LocalRecordedArtifact] = []
|
|
206
285
|
else:
|
|
286
|
+
# Record the canonical source on each downloaded artifact so it is a
|
|
287
|
+
# SOURCE node with a known origin (source_type/source_url), not a bare
|
|
288
|
+
# local file. This is what a downstream AI-BOM derives `downloadLocation`
|
|
289
|
+
# from — so it must be each file's OWN canonical URL, not a shared prefix.
|
|
290
|
+
source_type = parsed_source.scheme or None
|
|
207
291
|
output_artifacts = [
|
|
208
292
|
LocalRecordedArtifact(
|
|
209
293
|
path=file_info.local_path,
|
|
210
294
|
hashes={"blake3": str(file_info.hash)},
|
|
211
295
|
size=int(file_info.size or 0),
|
|
296
|
+
source_type=source_type,
|
|
297
|
+
source_url=_canonical_source_url(file_info, request, fetch_url, fetched_from_cache),
|
|
212
298
|
)
|
|
213
299
|
for file_info in transfer_result.downloaded_files
|
|
214
300
|
]
|
|
@@ -427,6 +513,9 @@ def _build_get_command(request: GetRequest) -> str:
|
|
|
427
513
|
user typed.
|
|
428
514
|
"""
|
|
429
515
|
parts = ["roar get", request.source]
|
|
516
|
+
if request.cache:
|
|
517
|
+
# Record the mirror so a reproduce replays cache-first-then-canonical.
|
|
518
|
+
parts.append(f"--cache {request.cache}")
|
|
430
519
|
if request.limit is not None:
|
|
431
520
|
parts.append(f"--limit {request.limit}")
|
|
432
521
|
if request.step_name:
|
|
@@ -9,6 +9,7 @@ roar put ALWAYS registers lineage with GLaaS. This is not optional.
|
|
|
9
9
|
|
|
10
10
|
from __future__ import annotations
|
|
11
11
|
|
|
12
|
+
import shlex
|
|
12
13
|
import time
|
|
13
14
|
from dataclasses import dataclass, field
|
|
14
15
|
from pathlib import Path
|
|
@@ -52,6 +53,47 @@ from .put_composites import (
|
|
|
52
53
|
from .results import PutCompositeRegistration, PutDryRunItem, PutUploadedFile
|
|
53
54
|
|
|
54
55
|
|
|
56
|
+
def build_put_command(
|
|
57
|
+
sources: list[str],
|
|
58
|
+
destination: str | None,
|
|
59
|
+
*,
|
|
60
|
+
message: str,
|
|
61
|
+
public: bool = True,
|
|
62
|
+
anonymous: bool = False,
|
|
63
|
+
no_tag: bool = False,
|
|
64
|
+
as_dataset: bool = False,
|
|
65
|
+
step_name: str | None = None,
|
|
66
|
+
) -> str:
|
|
67
|
+
"""Reconstruct a faithful ``roar put`` command string for the job record.
|
|
68
|
+
|
|
69
|
+
The recorded command drives ``roar reproduce``, so it must include the
|
|
70
|
+
destination and every provenance-relevant flag — not just the sources and
|
|
71
|
+
message. Interaction/mode flags (``--yes``, ``--dry-run``) are intentionally
|
|
72
|
+
omitted: they control confirmation/preview, not the published result.
|
|
73
|
+
"""
|
|
74
|
+
parts = ["roar", "put"]
|
|
75
|
+
if sources:
|
|
76
|
+
parts.extend(shlex.quote(s) for s in sources)
|
|
77
|
+
else:
|
|
78
|
+
parts.append("(session outputs)")
|
|
79
|
+
if destination:
|
|
80
|
+
parts.append(shlex.quote(destination))
|
|
81
|
+
if anonymous:
|
|
82
|
+
parts.append("--anonymous")
|
|
83
|
+
elif public is False:
|
|
84
|
+
parts.append("--private")
|
|
85
|
+
elif public:
|
|
86
|
+
parts.append("--public")
|
|
87
|
+
if no_tag:
|
|
88
|
+
parts.append("--no-tag")
|
|
89
|
+
if as_dataset:
|
|
90
|
+
parts.append("--as-dataset")
|
|
91
|
+
if step_name:
|
|
92
|
+
parts.extend(["--step-name", shlex.quote(step_name)])
|
|
93
|
+
parts.extend(["-m", shlex.quote(message)])
|
|
94
|
+
return " ".join(parts)
|
|
95
|
+
|
|
96
|
+
|
|
55
97
|
def _upload_progress_message(done: int, total: int, uploaded_bytes: int) -> str:
|
|
56
98
|
"""Status line for the upload spinner, e.g. ``Uploading 12/100 files · 1.10 GB``."""
|
|
57
99
|
return f"Uploading {done}/{total} files · {uploaded_bytes / 1e9:.2f} GB"
|
|
@@ -145,6 +187,7 @@ class PutService:
|
|
|
145
187
|
git_commit: str | None = None,
|
|
146
188
|
git_tag: str | None = None,
|
|
147
189
|
declared: bool = False,
|
|
190
|
+
command: str | None = None,
|
|
148
191
|
) -> PutResult:
|
|
149
192
|
"""
|
|
150
193
|
Execute a put operation.
|
|
@@ -294,6 +337,7 @@ class PutService:
|
|
|
294
337
|
git_context=git_context,
|
|
295
338
|
sources=sources,
|
|
296
339
|
message=message,
|
|
340
|
+
command=command,
|
|
297
341
|
uploads=uploads,
|
|
298
342
|
uploaded_files=uploaded_files,
|
|
299
343
|
artifacts_info=artifacts_info,
|
|
@@ -416,9 +460,10 @@ class PutService:
|
|
|
416
460
|
for item in composite_registrations
|
|
417
461
|
]
|
|
418
462
|
|
|
419
|
-
# Build command string
|
|
420
|
-
|
|
421
|
-
command
|
|
463
|
+
# Build command string. Prefer the faithful command (destination + flags)
|
|
464
|
+
# supplied by the caller; fall back to a destination-aware reconstruction.
|
|
465
|
+
if command is None:
|
|
466
|
+
command = build_put_command(sources, self._destination, message=message)
|
|
422
467
|
|
|
423
468
|
# Build metadata
|
|
424
469
|
metadata_json = build_put_operation_metadata_json(
|
|
@@ -551,6 +596,7 @@ class PutService:
|
|
|
551
596
|
git_context: GitContext,
|
|
552
597
|
sources: list[str],
|
|
553
598
|
message: str,
|
|
599
|
+
command: str | None = None,
|
|
554
600
|
uploads: list[_UploadedArtifact],
|
|
555
601
|
uploaded_files: list[PutUploadedFile],
|
|
556
602
|
artifacts_info: list[tuple[str, str]],
|
|
@@ -571,8 +617,8 @@ class PutService:
|
|
|
571
617
|
registration_errors: list[str] = []
|
|
572
618
|
lineage_composite_registrations: list[dict[str, Any]] = []
|
|
573
619
|
composite_registrations: list[dict[str, Any]] = []
|
|
574
|
-
|
|
575
|
-
|
|
620
|
+
if command is None:
|
|
621
|
+
command = build_put_command(sources, self._destination, message=message)
|
|
576
622
|
source_type = normalize_registration_source_type(destination_type)
|
|
577
623
|
|
|
578
624
|
provisional_metadata_json = build_put_operation_metadata_json(
|
|
@@ -100,7 +100,9 @@ def prepare_put_execution(
|
|
|
100
100
|
)
|
|
101
101
|
|
|
102
102
|
destination_type = _destination_type(destination)
|
|
103
|
-
composite_source_type =
|
|
103
|
+
composite_source_type = (
|
|
104
|
+
destination_type if destination_type in {"s3", "gs", "https", "hf"} else None
|
|
105
|
+
)
|
|
104
106
|
|
|
105
107
|
return PreparedPutExecution(
|
|
106
108
|
glaas_client=runtime.glaas_client,
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import json
|
|
5
6
|
import time
|
|
6
7
|
from dataclasses import dataclass
|
|
7
8
|
from typing import Any
|
|
@@ -329,14 +330,33 @@ def prepare_batch_registration_artifacts(
|
|
|
329
330
|
except (TypeError, ValueError):
|
|
330
331
|
size = 0
|
|
331
332
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
333
|
+
entry = {
|
|
334
|
+
"hashes": hashes,
|
|
335
|
+
"size": size,
|
|
336
|
+
"source_type": normalize_registration_source_type(artifact.get("source_type")),
|
|
337
|
+
"session_hash": session_hash,
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
# Carry the artifact's source URL into its registration metadata so GLaaS
|
|
341
|
+
# can emit the AI-BOM `downloadLocation` external reference. The batch
|
|
342
|
+
# payload previously dropped `source_url`, so source-tracked inputs
|
|
343
|
+
# (e.g. s3://…) reached GLaaS with a sourceType but no distribution URL.
|
|
344
|
+
source_url = artifact.get("source_url")
|
|
345
|
+
if source_url and entry["source_type"]:
|
|
346
|
+
existing = artifact.get("metadata")
|
|
347
|
+
if isinstance(existing, str):
|
|
348
|
+
try:
|
|
349
|
+
meta = json.loads(existing)
|
|
350
|
+
except (ValueError, TypeError):
|
|
351
|
+
meta = {}
|
|
352
|
+
elif isinstance(existing, dict):
|
|
353
|
+
meta = dict(existing)
|
|
354
|
+
else:
|
|
355
|
+
meta = {}
|
|
356
|
+
meta.setdefault("source_url", source_url)
|
|
357
|
+
entry["metadata"] = json.dumps(meta)
|
|
358
|
+
|
|
359
|
+
prepared.append(entry)
|
|
340
360
|
|
|
341
361
|
return prepared
|
|
342
362
|
|
|
@@ -206,6 +206,8 @@ def build_registration_package(
|
|
|
206
206
|
if composites:
|
|
207
207
|
package["composites"] = composites
|
|
208
208
|
|
|
209
|
+
if labels:
|
|
210
|
+
labels = _drop_labels_for_absent_jobs(labels, job_records)
|
|
209
211
|
if labels:
|
|
210
212
|
filtered_labels, label_detections = _filter_label_secrets(labels, omit_filter)
|
|
211
213
|
package["labels"] = filtered_labels
|
|
@@ -292,6 +294,38 @@ def _apply_redaction(
|
|
|
292
294
|
)
|
|
293
295
|
|
|
294
296
|
|
|
297
|
+
def _drop_labels_for_absent_jobs(
|
|
298
|
+
labels: list[dict[str, Any]],
|
|
299
|
+
job_records: list[dict[str, Any]],
|
|
300
|
+
) -> list[dict[str, Any]]:
|
|
301
|
+
"""Drop job-scoped labels whose target job is not in the package.
|
|
302
|
+
|
|
303
|
+
Labels are collected from the raw lineage, but the package's jobs are
|
|
304
|
+
noise-filtered by ``normalize_jobs_for_registration``. A job label left
|
|
305
|
+
pointing at a dropped job makes the package internally inconsistent — GLaaS
|
|
306
|
+
rejects it on publish with "Package label references a job not in the
|
|
307
|
+
package". The job label's target reaches the publish side through the job
|
|
308
|
+
record's ``job_uid`` (GLaaS's ``sourceUid``), so match on that. Non-job
|
|
309
|
+
labels (dag, artifact) are unaffected.
|
|
310
|
+
"""
|
|
311
|
+
package_job_uids = {str(job.get("job_uid")) for job in job_records if job.get("job_uid")}
|
|
312
|
+
kept: list[dict[str, Any]] = []
|
|
313
|
+
dropped = 0
|
|
314
|
+
for label in labels:
|
|
315
|
+
if str(label.get("entity_type")) == "job":
|
|
316
|
+
job_uid = label.get("job_uid")
|
|
317
|
+
if not isinstance(job_uid, str) or job_uid not in package_job_uids:
|
|
318
|
+
dropped += 1
|
|
319
|
+
continue
|
|
320
|
+
kept.append(label)
|
|
321
|
+
if dropped:
|
|
322
|
+
get_logger().debug(
|
|
323
|
+
"Dropped %d job label(s) referencing jobs not in the registration package",
|
|
324
|
+
dropped,
|
|
325
|
+
)
|
|
326
|
+
return kept
|
|
327
|
+
|
|
328
|
+
|
|
295
329
|
def _filter_label_secrets(
|
|
296
330
|
labels: list[dict[str, Any]],
|
|
297
331
|
omit_filter: OmitFilter | None,
|
|
@@ -894,6 +894,8 @@ def put_artifacts(request: PutRequest) -> PutResponse:
|
|
|
894
894
|
)
|
|
895
895
|
put_commit_on_remote = is_shareable_remote(prepared.git_context.repo)
|
|
896
896
|
|
|
897
|
+
from .put_execution import build_put_command
|
|
898
|
+
|
|
897
899
|
result = service.put_prepared(
|
|
898
900
|
prepared=prepared,
|
|
899
901
|
sources=request.sources,
|
|
@@ -902,6 +904,16 @@ def put_artifacts(request: PutRequest) -> PutResponse:
|
|
|
902
904
|
git_commit=git_commit,
|
|
903
905
|
git_tag=expected_tag,
|
|
904
906
|
declared=request.as_dataset,
|
|
907
|
+
command=build_put_command(
|
|
908
|
+
request.sources,
|
|
909
|
+
request.destination,
|
|
910
|
+
message=request.message,
|
|
911
|
+
public=request.public,
|
|
912
|
+
anonymous=request.anonymous,
|
|
913
|
+
no_tag=request.no_tag,
|
|
914
|
+
as_dataset=request.as_dataset,
|
|
915
|
+
step_name=request.step_name,
|
|
916
|
+
),
|
|
905
917
|
)
|
|
906
918
|
|
|
907
919
|
# Apply step name label if provided.
|
|
@@ -20,3 +20,8 @@ class ReproduceRequest:
|
|
|
20
20
|
package_sync: bool = False
|
|
21
21
|
list_requirements: bool = False
|
|
22
22
|
out_path: str | None = None
|
|
23
|
+
# Skip publish (`roar put`) steps — for third-party reproduction that
|
|
24
|
+
# rebuilds the artifact without re-publishing to the owner's destination.
|
|
25
|
+
no_puts: bool = False
|
|
26
|
+
# Emit an editable reproduction shell script instead of previewing/running.
|
|
27
|
+
emit_script: bool = False
|