roar-cli 0.4.0__tar.gz → 0.4.1__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.1}/PKG-INFO +2 -1
- {roar_cli-0.4.0 → roar_cli-0.4.1}/pyproject.toml +2 -1
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/analyzers/experiment_trackers.py +103 -3
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/get/requests.py +1 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/get/service.py +105 -16
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/publish/put_preparation.py +3 -1
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/publish/registration.py +28 -8
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/reproducibility/report.py +18 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/commands/get.py +11 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/commands/proxy.py +7 -3
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/commands/put.py +14 -2
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/commands/register.py +55 -18
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/commands/scope.py +16 -6
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/publish_intent.py +5 -0
- roar_cli-0.4.1/roar/cli/templates/agents/SKILL.md.tmpl +198 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/templates/agents/agents_section.md.tmpl +3 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/runtime/proxy_resource.py +22 -2
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/runtime/tracer.py +1 -1
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/download/hf.py +9 -3
- roar_cli-0.4.1/roar/integrations/storage/hf.py +146 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/storage/publish.py +5 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/publish_auth.py +71 -5
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/scope_config.py +4 -0
- roar_cli-0.4.0/roar/cli/templates/agents/SKILL.md.tmpl +0 -123
- {roar_cli-0.4.0 → roar_cli-0.4.1}/LICENSE +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/README.md +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/__main__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/analyzers/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/analyzers/base.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/composite/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/composite/canonical.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/composite/detect.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/composite/qualifying.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/get/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/get/results.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/get/transfer.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/git.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/label_rendering.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/labels.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/lookup/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/lookup/models.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/lookup/policy.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/lookup/refs.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/lookup/remote_artifacts.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/lookup/runner.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/publish/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/publish/anchor_attribution.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/publish/blake3_upgrade.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/publish/collection.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/publish/composite_builder.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/publish/composites.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/publish/datasets.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/publish/form_composites.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/publish/git_remote.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/publish/job_links.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/publish/job_preparation.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/publish/lineage.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/publish/lineage_composite_formation.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/publish/lineage_composites.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/publish/metadata.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/publish/put_composites.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/publish/put_execution.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/publish/register_execution.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/publish/register_preparation.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/publish/register_preview_jobs.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/publish/register_tag_push.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/publish/registration_package.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/publish/remote_job_uids.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/publish/remote_registry.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/publish/requests.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/publish/results.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/publish/runtime.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/publish/secrets.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/publish/service.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/publish/session.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/publish/source_resolution.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/publish/targets.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/publish/view_edges.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/query/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/query/dag.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/query/db_status.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/query/diff.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/query/diff_engine.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/query/diff_graph.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/query/diff_refs.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/query/git_readiness.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/query/inputs.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/query/label.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/query/lineage.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/query/log.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/query/requests.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/query/results.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/query/show.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/query/status.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/query/tag.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/reproduce/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/reproduce/environment.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/reproduce/lookup.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/reproduce/requests.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/reproduce/results.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/reproduce/service.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/reproducibility/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/run/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/run/dag_references.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/run/dirty_tree_classify.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/run/dirty_tree_error.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/run/execution.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/run/gitignore_suggest.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/run/output_followup.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/run/requests.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/run/service.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/run/verbosity.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/system_labels.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/tags.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/workflow/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/workflow/requests.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/workflow/results.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/application/workflow/service.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/auth_store.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/backends/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/backends/local/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/backends/local/plugin.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/backends/osmo/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/backends/osmo/config.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/backends/osmo/export.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/backends/osmo/host_execution.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/backends/osmo/lineage.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/backends/osmo/plugin.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/backends/osmo/runtime_bundle.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/backends/osmo/submit.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/backends/osmo/workflow.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/backends/ray/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/backends/ray/_agent_names.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/backends/ray/collector.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/backends/ray/config.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/backends/ray/constants.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/backends/ray/env_contract.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/backends/ray/fragment.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/backends/ray/fragment_reconstituter.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/backends/ray/node_agent.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/backends/ray/plugin.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/backends/ray/proxy_fragments.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/backends/ray/roar_worker.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/backends/ray/runtime_hooks.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/backends/ray/s3_key_paths.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/backends/ray/submit.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/backends/ray/submit_context.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/_format.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/_tag_kinds.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/command_registry.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/commands/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/commands/auth.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/commands/build.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/commands/config.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/commands/dag.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/commands/db.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/commands/diff.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/commands/env.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/commands/export_registration_package.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/commands/filter.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/commands/init.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/commands/init_agents.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/commands/inputs.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/commands/label.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/commands/lineage.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/commands/log.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/commands/login.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/commands/logout.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/commands/osmo.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/commands/pop.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/commands/projects.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/commands/reproduce.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/commands/reset.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/commands/run.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/commands/session.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/commands/show.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/commands/status.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/commands/tag.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/commands/telemetry.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/commands/tracer.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/commands/tui.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/commands/whoami.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/commands/workflow.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/context.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/cli/decorators.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/core/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/core/bootstrap.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/core/canonical_session.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/core/digests.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/core/dto/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/core/dto/registration.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/core/exceptions.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/core/interfaces/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/core/interfaces/config.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/core/interfaces/lineage.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/core/interfaces/logger.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/core/interfaces/presenter.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/core/interfaces/provenance.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/core/interfaces/registration.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/core/interfaces/repositories.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/core/interfaces/reproduction.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/core/interfaces/run.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/core/interfaces/services.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/core/interfaces/telemetry.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/core/interfaces/vcs.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/core/label_constants.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/core/label_origins.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/core/logging.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/core/models/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/core/models/artifact.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/core/models/base.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/core/models/dag.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/core/models/dataset_identifier.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/core/models/glaas.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/core/models/job.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/core/models/lineage.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/core/models/provenance.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/core/models/run.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/core/models/session.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/core/models/telemetry.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/core/models/vcs.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/core/operation_metadata.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/core/session_hash.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/core/step_name.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/core/tracer_modes.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/core/validation.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/db/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/db/context.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/db/engine.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/db/hashing/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/db/hashing/backend.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/db/hashing/blake3.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/db/models.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/db/query_context.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/db/repositories/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/db/repositories/artifact.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/db/repositories/collection.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/db/repositories/composite.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/db/repositories/hash_cache.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/db/repositories/job.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/db/repositories/label.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/db/repositories/session.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/db/schema.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/db/services/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/db/services/hashing.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/db/services/job_recording.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/db/services/lineage.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/db/services/session.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/db/step_priority.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/cluster/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/cluster/bridge.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/cluster/proxy.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/cluster/proxy_config.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/fragments/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/fragments/lineage.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/fragments/models.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/fragments/reconstitution.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/fragments/sessions.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/fragments/transport.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/framework/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/framework/contract.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/framework/planning.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/framework/registry.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/framework/runtime_imports.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/provenance/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/provenance/assembler.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/provenance/build_pip_collector.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/provenance/build_tool_collector.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/provenance/data_loader.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/provenance/file_filter.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/provenance/package_collector.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/provenance/process_summarizer.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/provenance/runtime_collector.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/provenance/service.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/recording/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/recording/dataset_identifier.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/recording/dataset_metadata.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/recording/dataset_profile.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/recording/job_recording.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/reproduction/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/reproduction/environment_setup.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/reproduction/installers.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/reproduction/pipeline_executor.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/reproduction/pipeline_metadata.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/runtime/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/runtime/abi_probe.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/runtime/active_runs.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/runtime/backup.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/runtime/coordinator.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/runtime/driver_entrypoint.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/runtime/errors.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/runtime/host_execution.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/runtime/inject/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/runtime/inject/sitecustomize.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/runtime/inject/support.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/runtime/inject/tracker.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/runtime/lazy_install.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/runtime/resources.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/runtime/signal_handler.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/runtime/tracer_backends.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/runtime/tracer_banner.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/execution/runtime/worker_bootstrap.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/filters/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/filters/files.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/filters/omit.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/glaas_auth.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/glaas_client.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/bootstrap.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/config/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/config/access.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/config/loader.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/config/raw.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/config/schema.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/discovery.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/download/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/download/base.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/download/gcs.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/download/get.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/download/http.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/download/noop.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/download/s3.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/git/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/git/base.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/git/context.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/git/provider.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/glaas/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/glaas/auth.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/glaas/client.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/glaas/fragment_streamer.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/glaas/registration/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/glaas/registration/_artifact_ref.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/glaas/registration/artifact.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/glaas/registration/coordinator.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/glaas/registration/job.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/glaas/registration/session.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/glaas/transport.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/registry.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/resolution.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/storage/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/storage/base.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/storage/gcs.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/storage/memory.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/storage/noop.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/storage/s3.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/telemetry/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/telemetry/base.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/integrations/telemetry/wandb.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/presenters/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/presenters/console.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/presenters/dag_data_builder.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/presenters/dag_renderer.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/presenters/diff_renderer.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/presenters/formatting.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/presenters/null.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/presenters/run_report.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/presenters/show_renderer.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/presenters/spinner.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/presenters/terminal.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/require.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/telemetry/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/telemetry/_io.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/telemetry/capabilities.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/telemetry/config.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/telemetry/hooks.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/telemetry/install.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/telemetry/paths.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/telemetry/payload.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/telemetry/queue.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/telemetry/stats.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/telemetry/uploader.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/tui/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/tui/app.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/tui/data.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/tui/screens/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/tui/screens/config_editor.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/tui/screens/label_editor.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/tui/screens/launcher.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/tui/screens/log.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/tui/screens/main.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/tui/screens/search.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/tui/screens/session_picker.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/tui/tmux.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/tui/widgets/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/tui/widgets/detail.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/utils/__init__.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/utils/cloud.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/utils/git_url.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/roar/version_check.py +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/Cargo.lock +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/Cargo.toml +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/crates/artifact-hash-core/Cargo.toml +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/crates/artifact-hash-core/src/lib.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/crates/artifact-hash-py/Cargo.toml +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/crates/artifact-hash-py/src/lib.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/crates/tracer-fd/Cargo.toml +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/crates/tracer-fd/src/lib.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/crates/tracer-runtime/Cargo.toml +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/crates/tracer-runtime/src/lib.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/crates/tracer-schema/Cargo.toml +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/crates/tracer-schema/src/lib.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/services/proxy/Cargo.lock +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/services/proxy/Cargo.toml +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/services/proxy/src/forward.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/services/proxy/src/main.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/services/proxy/src/s3.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/tracers/ebpf/common/Cargo.toml +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/tracers/ebpf/common/src/lib.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/tracers/ebpf/probe/Cargo.toml +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/tracers/ebpf/probe/rust-toolchain.toml +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/tracers/ebpf/probe/src/main.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/tracers/ebpf/userspace/Cargo.toml +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/tracers/ebpf/userspace/build.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/tracers/ebpf/userspace/src/attach.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/tracers/ebpf/userspace/src/bin/roard.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/tracers/ebpf/userspace/src/client.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/tracers/ebpf/userspace/src/daemon.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/tracers/ebpf/userspace/src/events.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/tracers/ebpf/userspace/src/ipc.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/tracers/ebpf/userspace/src/lib.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/tracers/ebpf/userspace/src/main.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/tracers/ebpf/userspace/src/state.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/tracers/preload/Cargo.toml +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/tracers/preload/build.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/tracers/preload/src/bin/io_fixture.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/tracers/preload/src/interpose.c +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/tracers/preload/src/ipc.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/tracers/preload/src/lib.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/tracers/preload/src/main.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/tracers/preload/tests/comprehensive.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/tracers/preload/tests/standalone.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/tracers/ptrace/Cargo.toml +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/tracers/ptrace/rustfmt.toml +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/tracers/ptrace/src/arch.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/tracers/ptrace/src/main.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/rust/tracers/ptrace/src/seccomp.rs +0 -0
- {roar_cli-0.4.0 → roar_cli-0.4.1}/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.1
|
|
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.1"
|
|
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]
|
|
@@ -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:
|
|
@@ -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
|
|
|
@@ -75,6 +75,8 @@ def build_report(
|
|
|
75
75
|
on_glaas: bool | None = None,
|
|
76
76
|
single_commit: bool = True,
|
|
77
77
|
untracked_paths: list[str] | None = None,
|
|
78
|
+
secrets_detected: int | None = None,
|
|
79
|
+
secrets_scanned: bool = True,
|
|
78
80
|
notes: dict[str, str] | None = None,
|
|
79
81
|
na: dict[str, str] | None = None,
|
|
80
82
|
) -> ReproducibilityReport:
|
|
@@ -147,6 +149,22 @@ def build_report(
|
|
|
147
149
|
"only on this machine — run `roar register` to publish it",
|
|
148
150
|
)
|
|
149
151
|
)
|
|
152
|
+
# Receipt-only, register/put: when the secret scan runs, any hits are redacted
|
|
153
|
+
# so the published lineage is clean (the note shows none/N redacted) and this
|
|
154
|
+
# passes. But it must NOT pass — and must not claim "none detected" — when the
|
|
155
|
+
# scan was disabled (registration.omit.enabled=false): that's "not scanned", not
|
|
156
|
+
# "scanned clean", and reporting it green would be false assurance. Doesn't bear
|
|
157
|
+
# on reproducibility, so `reproduce` omits it (secrets_detected None).
|
|
158
|
+
if secrets_detected is not None:
|
|
159
|
+
checks.append(
|
|
160
|
+
ReproCheck(
|
|
161
|
+
"secrets",
|
|
162
|
+
"no secrets in published lineage",
|
|
163
|
+
secrets_scanned,
|
|
164
|
+
"secret scan disabled (registration.omit.enabled=false) — the published "
|
|
165
|
+
"lineage was NOT scanned for secrets",
|
|
166
|
+
)
|
|
167
|
+
)
|
|
150
168
|
report = ReproducibilityReport(checks=checks)
|
|
151
169
|
for check in report.checks:
|
|
152
170
|
if notes and check.key in notes:
|
|
@@ -78,6 +78,15 @@ from ..decorators import require_init
|
|
|
78
78
|
"even past the 64 MB budget. Downloads them; without this they are excluded from "
|
|
79
79
|
"the anchor's identity (LFS-only) when over budget.",
|
|
80
80
|
)
|
|
81
|
+
@click.option(
|
|
82
|
+
"--cache",
|
|
83
|
+
"cache",
|
|
84
|
+
default=None,
|
|
85
|
+
help="Fetch bytes from this mirror URL instead of SOURCE, while recording "
|
|
86
|
+
"SOURCE as the canonical origin (so the AI-BOM downloadLocation stays the public "
|
|
87
|
+
"URL, not the private mirror). The mirror is hash-verified against --hash when "
|
|
88
|
+
"given; roar falls back to SOURCE on miss/unreachable/mismatch.",
|
|
89
|
+
)
|
|
81
90
|
@click.pass_obj
|
|
82
91
|
@require_init
|
|
83
92
|
def get(
|
|
@@ -93,6 +102,7 @@ def get(
|
|
|
93
102
|
step_name: str | None,
|
|
94
103
|
limit: int | None,
|
|
95
104
|
full_anchor: bool,
|
|
105
|
+
cache: str | None,
|
|
96
106
|
) -> None:
|
|
97
107
|
"""Download artifacts from cloud storage and record in the local DAG.
|
|
98
108
|
|
|
@@ -159,6 +169,7 @@ def get(
|
|
|
159
169
|
step_name=step_name,
|
|
160
170
|
limit=limit,
|
|
161
171
|
full_anchor=full_anchor,
|
|
172
|
+
cache=cache,
|
|
162
173
|
)
|
|
163
174
|
)
|
|
164
175
|
except FileExistsError as e:
|
|
@@ -82,8 +82,9 @@ def proxy_disable() -> None:
|
|
|
82
82
|
def proxy_start() -> None:
|
|
83
83
|
"""Start a standalone S3 proxy daemon.
|
|
84
84
|
|
|
85
|
-
The daemon runs in the background.
|
|
86
|
-
|
|
85
|
+
The daemon runs in the background. Point S3 clients at its port with
|
|
86
|
+
AWS_ENDPOINT_URL_S3 (SDKs) / S3_ENDPOINT_URL (s5cmd) to route S3 traffic
|
|
87
|
+
through the proxy.
|
|
87
88
|
"""
|
|
88
89
|
from ...execution.cluster.proxy import ProxyService
|
|
89
90
|
from ...integrations.config import get_roar_dir
|
|
@@ -104,7 +105,10 @@ def proxy_start() -> None:
|
|
|
104
105
|
click.echo(f"Proxy daemon started (pid={info['pid']}, port={info['port']}).")
|
|
105
106
|
click.echo("")
|
|
106
107
|
click.echo("To use it:")
|
|
107
|
-
click.echo(
|
|
108
|
+
click.echo(
|
|
109
|
+
f" export AWS_ENDPOINT_URL_S3=http://127.0.0.1:{info['port']} # boto3, aws cli"
|
|
110
|
+
)
|
|
111
|
+
click.echo(f" export S3_ENDPOINT_URL=http://127.0.0.1:{info['port']} # s5cmd")
|
|
108
112
|
except RuntimeError as e:
|
|
109
113
|
raise click.ClickException(str(e)) from e
|
|
110
114
|
|
|
@@ -14,6 +14,10 @@ import click
|
|
|
14
14
|
from ...application.publish.requests import PutRequest
|
|
15
15
|
from ...application.publish.results import PutResponse
|
|
16
16
|
from ...application.publish.service import put_artifacts
|
|
17
|
+
from ...publish_auth import (
|
|
18
|
+
reset_requested_publish_visibility,
|
|
19
|
+
set_requested_publish_visibility,
|
|
20
|
+
)
|
|
17
21
|
from ..context import RoarContext
|
|
18
22
|
from ..decorators import require_init
|
|
19
23
|
from ..publish_intent import (
|
|
@@ -169,8 +173,11 @@ def put(
|
|
|
169
173
|
|
|
170
174
|
\b
|
|
171
175
|
Destination formats:
|
|
172
|
-
s3://bucket/prefix
|
|
173
|
-
gs://bucket/prefix
|
|
176
|
+
s3://bucket/prefix AWS S3
|
|
177
|
+
gs://bucket/prefix Google Cloud Storage
|
|
178
|
+
hf://owner/repo[/path] Hugging Face Hub (model repo; recorded as the
|
|
179
|
+
public downloadLocation)
|
|
180
|
+
hf://datasets/owner/repo Hugging Face Hub dataset repo
|
|
174
181
|
|
|
175
182
|
\b
|
|
176
183
|
Examples:
|
|
@@ -221,6 +228,9 @@ def put(
|
|
|
221
228
|
click.echo("Publication aborted.")
|
|
222
229
|
raise SystemExit(1)
|
|
223
230
|
|
|
231
|
+
# Record the explicit --public/--private choice so the publish resolves a
|
|
232
|
+
# flag-reconciled scope_request visibility (see publish_auth._scope_visibility).
|
|
233
|
+
_vis_token = set_requested_publish_visibility(public)
|
|
224
234
|
try:
|
|
225
235
|
response = put_artifacts(
|
|
226
236
|
PutRequest(
|
|
@@ -242,6 +252,8 @@ def put(
|
|
|
242
252
|
raise click.ClickException(str(e)) from e
|
|
243
253
|
except Exception as e: # pragma: no cover - defensive CLI boundary
|
|
244
254
|
raise click.ClickException(f"Unexpected error during put: {e}") from e
|
|
255
|
+
finally:
|
|
256
|
+
reset_requested_publish_visibility(_vis_token)
|
|
245
257
|
|
|
246
258
|
for warning in response.warnings:
|
|
247
259
|
click.echo(f"Warning: {warning}", err=True)
|