outerloop-science 0.2.0rc2__tar.gz → 0.2.0rc4__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.
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/CHANGELOG.md +17 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/CITATION.cff +2 -2
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/PKG-INFO +1 -1
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/docs/install.md +82 -8
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/pyproject.toml +5 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/scripts/README.md +1 -1
- outerloop_science-0.2.0rc4/scripts/install_claude.sh +82 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/scripts/tick_chain.sbatch +3 -1
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/scripts/tick_deploy.sh +23 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/scripts/tick_resident.sh +3 -1
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/__init__.py +1 -1
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/attempt.py +302 -113
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/cli.py +114 -23
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/compute.py +21 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/dispatch.py +5 -2
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/github.py +33 -5
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/harness.py +36 -9
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/image.py +6 -1
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/init.py +56 -16
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/measure.py +46 -2
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/orchestrator.py +3 -1
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/runstate.py +122 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/steward.py +20 -2
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/tick.py +154 -34
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/conftest.py +15 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_app_permissions.py +2 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_attempt.py +380 -7
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_attempt_review.py +93 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_dispatch.py +44 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_github.py +31 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_harness.py +44 -15
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_hermes_harness.py +2 -1
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_image.py +18 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_init.py +60 -8
- outerloop_science-0.2.0rc4/tests/test_install_harness.py +218 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_local_compute.py +47 -2
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_measure.py +100 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_orchestrator.py +6 -2
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_runstate.py +128 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_start.py +288 -40
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_tick.py +300 -4
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_tick_resident.py +10 -2
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/.gitignore +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/.pre-commit-config.yaml +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/.python-version +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/CLAUDE.md +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/CONTRIBUTING.md +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/LICENSE +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/NOTICE +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/README.md +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/RELEASING.md +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/SECURITY.md +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/containers/README.md +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/containers/agent-py312.def +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/docs/assets/icon-dark.svg +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/docs/assets/icon-light.svg +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/docs/assets/icon.svg +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/docs/community.md +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/docs/compute.md +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/docs/contract.md +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/docs/design/agent-protocols.md +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/docs/design/agent-substrate.md +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/docs/design/architecture.md +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/docs/design/base-reintegration.md +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/docs/design/consolidation.md +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/docs/design/dispatcher.md +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/docs/design/eval-cache.md +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/docs/design/external.md +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/docs/design/github-app-auth.md +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/docs/design/headline.md +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/docs/design/judge-placement.md +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/docs/design/lifecycle.md +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/docs/design/meta.md +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/docs/design/onboarding.md +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/docs/design/orchestrator-verify.md +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/docs/design/public-surface.md +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/docs/design/research-lines.md +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/docs/design/research-loop-buildout.md +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/docs/design/research-loop.md +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/docs/design/resident-tick.md +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/docs/design/review-placement.md +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/docs/design/reviewer-infra.md +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/docs/design/role-cli.md +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/docs/design/roles.md +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/docs/design/scaling.md +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/docs/design/session-watcher.md +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/docs/reviewer.md +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/docs/roadmap.md +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/docs/validation/author-syscalls.md +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/examples/review.yml +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/scripts/install_codex.sh +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/scripts/install_hermes.sh +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/scripts/requeue_moved_successors.sh +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/scripts/setup_branch_protection.sh +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/scripts/sweep_git_locks.sh +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/__main__.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/appauth.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/appmanifest.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/brief.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/climbboard.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/contract.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/contract_cli.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/disk.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/evalcache.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/housekeeping.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/hypothesis.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/inbox.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/intake.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/launchlog.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/limits.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/maintain.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/maintain_agent_cli.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/maintain_post_cli.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/markers.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/panel.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/paths.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/posting.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/progress.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/py.typed +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/review.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/review_agent.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/review_agent_cli.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/review_post_cli.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/review_summarize_cli.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/role_runner.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/roles.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/rolespec.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/style.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/syscall.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/syscall_cli.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/verifier.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/verify_agent.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/verify_agent_cli.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/verify_post_cli.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/src/outerloop/watcher.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/fakes.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/helpers.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_appauth.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_appmanifest.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_bot_aliases.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_bot_login.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_brief.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_channel_dir.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_climbboard.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_codex_harness.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_compute.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_contract.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_contract_cli.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_contract_names.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_disk.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_evalcache.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_hardening.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_housekeeping.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_import.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_inbox.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_intake.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_launchlog.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_lifecycle_cli.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_limits.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_maintain.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_markers.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_measure_and_decide.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_messages.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_packaging.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_panel.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_paths.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_posting.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_progress.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_requeue_moved_successors.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_review.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_review_agent.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_review_agent_cli.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_review_hardening.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_review_policy.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_review_summarize.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_role_runner.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_rolespec.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_steward.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_sweep_git_locks.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_syscall.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_syscall_cli.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_tick_chain_successors.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_tiers.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_verifier.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_verify_agent.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_verify_agent_cli.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_version.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/tests/test_watcher.py +0 -0
- {outerloop_science-0.2.0rc2 → outerloop_science-0.2.0rc4}/uv.lock +0 -0
|
@@ -20,12 +20,29 @@ launch arrays in parallel. The board shows running GPU jobs. `OUTERLOOP_LOCAL_GP
|
|
|
20
20
|
overrides GPU detection; `0` disables allocation. Submissions still wait for all
|
|
21
21
|
tasks to finish.
|
|
22
22
|
|
|
23
|
+
### Added
|
|
24
|
+
|
|
25
|
+
- `outerloop init` installs a missing author CLI and records its path; `--no-install-harness` opts out. Claude has a pinned, SHA256-verified installer.
|
|
26
|
+
|
|
27
|
+
- `OUTERLOOP_TICK_HOST=login` (or `--tick-host login`) runs a niced foreground tick loop against Slurm, with one tick lease per state root.
|
|
28
|
+
- `OUTERLOOP_QOS` sets the QOS for every submitted Slurm job.
|
|
29
|
+
- `OUTERLOOP_APPTAINER_BIN` selects the container executable on compute nodes.
|
|
30
|
+
- `<root>/HOLD_LAUNCHES` holds fresh kernel launches while existing runs, wake delivery, and the tick chain continue; remove the file to resume.
|
|
31
|
+
|
|
23
32
|
### Removed
|
|
24
33
|
|
|
25
34
|
- The pre-rename names are gone. The `AUTORESEARCH_*` environment names are no longer read by the package, the `.env` reader, the chain or the deploy step. `~/.config/autoresearch/`, `.autoresearch.yaml`, the `.autoresearch` channel directory, the `~/.autoresearch` local root default and `~/autoresearch-images` are no longer looked for. The `autoresearch-resident` and `autoresearch-tick` job names are no longer recognized. The `harness_key` file, the `*_HARNESS_KEY_FILE` setting and the `climb_job_id` record field are gone. Before upgrading, rename the `.env` keys, the config directory and the image directory. Cancel a resident or chain still queued under an old job name (`scancel --name autoresearch-resident`, or `scancel --name autoresearch-tick`) before running `outerloop start`: the guard against two loops on one root knows only the current name. Old `autoresearch:` comment markers are still recognized.
|
|
26
35
|
|
|
27
36
|
### Fixed
|
|
28
37
|
|
|
38
|
+
- The measurer waits up to 90 seconds for the files of a finished evaluation job. A filesystem delay no longer ends a measured improvement as a negative result.
|
|
39
|
+
- `outerloop start` refuses to run when the configured author's CLI is missing: it checks the recorded path, else PATH, else `~/.local/bin`, and names the install command and `outerloop init --force`.
|
|
40
|
+
|
|
41
|
+
- Ending line snapshots push once, with the kernel's GitHub auth. Without auth nothing is pushed and the log says so. A refused push is retried only when the remote line moved.
|
|
42
|
+
- PRs under `merge: auto` say why self-merge is waiting, and the publish records and logs the bless decision.
|
|
43
|
+
|
|
44
|
+
- A timed-out local job could leave its GPUs reserved until the next submit; they are now released once its process group is gone.
|
|
45
|
+
|
|
29
46
|
- The tick log says why a blessed PR is not merged yet (a message waits for the author, the run sleeps on jobs, the base moved, and so on), one line per sweep.
|
|
30
47
|
- Runs retain their hypothesis through review. The status strip and sibling view carry it with the PR link, and the brief asks authors to check the view, refreshed at every wake, before choosing a direction and before submitting.
|
|
31
48
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: outerloop-science
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.0rc4
|
|
4
4
|
Summary: Autonomous research agents that improve the benchmark you point them at, one verified pull request at a time
|
|
5
5
|
Project-URL: Homepage, https://outerloop.science
|
|
6
6
|
Project-URL: Repository, https://github.com/outerloop-science/outerloop
|
|
@@ -295,6 +295,35 @@ says so — rerun `outerloop init --force` online, or set the login in the
|
|
|
295
295
|
|
|
296
296
|
### 2c. Run the loop
|
|
297
297
|
|
|
298
|
+
When the configured author's CLI is missing, `outerloop init` installs it from
|
|
299
|
+
a pinned release and records its path. An existing executable is kept.
|
|
300
|
+
Use `--no-install-harness` to skip this step. To install by hand from the
|
|
301
|
+
outerloop checkout, run `bash scripts/install_claude.sh [target_path]` or
|
|
302
|
+
`bash scripts/install_codex.sh [target_path]`, then rerun `outerloop init --force`.
|
|
303
|
+
The default target is `$OUTERLOOP_<BACKEND>_BIN`, else `~/.local/bin/<backend>`.
|
|
304
|
+
Claude 2.1.272 is pinned for Linux x64 (glibc/musl) and ARM64; other platforms
|
|
305
|
+
are refused. Installation needs `curl`, `sha256sum`, and a writable target
|
|
306
|
+
directory. Hermes remains a review backend, provisioned with
|
|
307
|
+
`bash scripts/install_hermes.sh [target_dir]`.
|
|
308
|
+
|
|
309
|
+
**Host prerequisites for model backends.** From the outerloop checkout:
|
|
310
|
+
|
|
311
|
+
- Claude, as author or reviewer: the pinned Claude Code CLI; install with
|
|
312
|
+
`bash scripts/install_claude.sh`.
|
|
313
|
+
- Codex, as author or reviewer: the pinned Codex CLI; install with
|
|
314
|
+
`bash scripts/install_codex.sh`.
|
|
315
|
+
- Hermes, as reviewer only (not an author backend): the pinned hermes-agent
|
|
316
|
+
source checkout, run through `uv`; install with `bash scripts/install_hermes.sh`.
|
|
317
|
+
|
|
318
|
+
`init` records the absolute Claude
|
|
319
|
+
or Codex path found on PATH (or in `~/.local/bin`) as `OUTERLOOP_<BACKEND>_BIN`.
|
|
320
|
+
`start` checks only the configured author's CLI: the recorded path takes
|
|
321
|
+
precedence, otherwise it searches PATH, then `~/.local/bin`. A missing or non-executable CLI stops
|
|
322
|
+
launch before any job runs. After installing or moving it, run
|
|
323
|
+
`outerloop init --force` to record its path again. `--dry-run` prints the launch
|
|
324
|
+
command without checking the CLI. For Hermes, set `REVIEW_HERMES_REPO` to the installed checkout (the installer
|
|
325
|
+
defaults to `~/hermes-agent`); contained review sessions bind its source read-only.
|
|
326
|
+
|
|
298
327
|
The quickest path is the guided setup:
|
|
299
328
|
|
|
300
329
|
```bash
|
|
@@ -321,7 +350,7 @@ that can reach GitHub and your LLM provider works.
|
|
|
321
350
|
you start it again. On a headless machine start it under `nohup` or in a
|
|
322
351
|
tmux window, or as a user service.
|
|
323
352
|
|
|
324
|
-
**Updates.** A Slurm deployment runs from a checkout, and
|
|
353
|
+
**Updates.** A resident Slurm deployment runs from a checkout, and
|
|
325
354
|
`OUTERLOOP_AUTO_UPDATE` in `.env` says whether the deploy step moves it. `off`,
|
|
326
355
|
the default, leaves the checkout alone: you upgrade when you choose, and the
|
|
327
356
|
loop keeps running the code you validated. `release` moves it to the newest
|
|
@@ -334,6 +363,44 @@ the installed package, which has no such policy: run `outerloop upgrade` to move
|
|
|
334
363
|
it to the newest release (add `--pre` to track pre-releases), then start it
|
|
335
364
|
again. That is `pip install --upgrade outerloop-science` under one verb.
|
|
336
365
|
|
|
366
|
+
#### Login-node loop
|
|
367
|
+
|
|
368
|
+
Use this when no Slurm partition can start a resident tick within your cadence
|
|
369
|
+
and the site permits a long-lived process on the login node. In
|
|
370
|
+
`~/.config/outerloop/.env`, set:
|
|
371
|
+
|
|
372
|
+
```bash
|
|
373
|
+
OUTERLOOP_TICK_HOST=login
|
|
374
|
+
OUTERLOOP_QOS=priority
|
|
375
|
+
OUTERLOOP_APPTAINER_BIN=/cm/local/apps/apptainer/current/bin/apptainer
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
Run `outerloop start` from your checkout with the usual shared `OUTERLOOP_ROOT`.
|
|
379
|
+
`--tick-host login` overrides the environment, which overrides `.env`.
|
|
380
|
+
`resident` is the default on Slurm; local compute still runs locally.
|
|
381
|
+
The login loop requires `sbatch` on PATH, runs in the foreground at nice +10,
|
|
382
|
+
and submits compute to Slurm. QOS applies to all submitted jobs; the Apptainer
|
|
383
|
+
path is used on compute nodes. The tick only checks the image file exists and
|
|
384
|
+
does not run Apptainer on the login node. Empty QOS uses Slurm's default;
|
|
385
|
+
an empty binary setting uses `apptainer`.
|
|
386
|
+
|
|
387
|
+
Only one loop may own a state root. Every foreground loop, local or login,
|
|
388
|
+
holds the root's `TICK` lease (holder `host:pid`, heartbeat and the holder's
|
|
389
|
+
cadence written each tick); a file lock refuses a second loop while the owner
|
|
390
|
+
runs. `outerloop start` refuses any loop while the lease is held, and a login
|
|
391
|
+
loop while a resident chain is queued or running; a resident submission that
|
|
392
|
+
finds the lease taken meanwhile withdraws its job, and a login loop that
|
|
393
|
+
finds a resident queued after taking the lease stops. After a crash the next
|
|
394
|
+
start on the same host takes the lease at once, and a start from another
|
|
395
|
+
host once the heartbeat is three of the holder's cadences old (file locks may
|
|
396
|
+
not reach across nodes); a loop whose record was overwritten from another
|
|
397
|
+
node stops at its next heartbeat. Ctrl-C or SIGTERM releases the lease. Use
|
|
398
|
+
tmux or a user service if the process should survive your terminal.
|
|
399
|
+
|
|
400
|
+
The login loop does **not auto-update**, even with `OUTERLOOP_AUTO_UPDATE=main`.
|
|
401
|
+
To restart or upgrade: stop the process, run `git pull`, run `uv sync`, then
|
|
402
|
+
run `outerloop start` again. Settings from `.env` are exported only at launch.
|
|
403
|
+
|
|
337
404
|
### Upgrading
|
|
338
405
|
|
|
339
406
|
1. Run `outerloop upgrade` (add `--pre` for pre-releases).
|
|
@@ -397,13 +464,20 @@ lesser of 10 minutes and half the cadence), and `OUTERLOOP_MAX_JOB_MINUTES` caps
|
|
|
397
464
|
the walltime the tick requests for the climb and author-sleep wake jobs it sizes
|
|
398
465
|
(clamped under a code ceiling).
|
|
399
466
|
|
|
400
|
-
**
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
467
|
+
**Three operator switches.** `touch <root>/PAUSE` stops tick work except the
|
|
468
|
+
heartbeat; jobs already running continue. The resident chain drains on it (it
|
|
469
|
+
cancels its successor and exits), so after `rm <root>/PAUSE` run `outerloop
|
|
470
|
+
start` there; the per-tick chain and the local loop resume on their own at the
|
|
471
|
+
next tick.
|
|
472
|
+
`touch <root>/DISARM_WAKE` stops wake delivery by the sweep and by queued wake
|
|
473
|
+
jobs until `rm <root>/DISARM_WAKE`, while fresh launches, ending records, and
|
|
474
|
+
the chain keep running (the starting environment's `OUTERLOOP_DISPATCH_WAKE=0`
|
|
475
|
+
also disarms wakes; it is not read from `.env`).
|
|
476
|
+
`touch <root>/HOLD_LAUNCHES` stops fresh intake, self-initiated, and steward runs
|
|
477
|
+
until `rm <root>/HOLD_LAUNCHES`, with no chain restart, while the sweep, wake and
|
|
478
|
+
message delivery, GitHub polling, self-merge sweep, board, and ending records
|
|
479
|
+
continue; existing runs keep spending, including their panels, author sessions,
|
|
480
|
+
and the authors' own `launch` submissions.
|
|
407
481
|
|
|
408
482
|
**Local mode without an image.** On a machine with no Apptainer image,
|
|
409
483
|
`OUTERLOOP_COMPUTE=local` still runs. Sessions run under the harness's own
|
|
@@ -59,6 +59,11 @@ path = "src/outerloop/__init__.py"
|
|
|
59
59
|
[tool.hatch.build.targets.wheel]
|
|
60
60
|
packages = ["src/outerloop"]
|
|
61
61
|
|
|
62
|
+
[tool.hatch.build.targets.wheel.force-include]
|
|
63
|
+
"scripts/install_claude.sh" = "outerloop/_installers/install_claude.sh"
|
|
64
|
+
"scripts/install_codex.sh" = "outerloop/_installers/install_codex.sh"
|
|
65
|
+
"scripts/install_hermes.sh" = "outerloop/_installers/install_hermes.sh"
|
|
66
|
+
|
|
62
67
|
[tool.ruff]
|
|
63
68
|
line-length = 100
|
|
64
69
|
target-version = "py312"
|
|
@@ -12,4 +12,4 @@ runs the local loop elsewhere, reading placement from `~/.config/outerloop/.env`
|
|
|
12
12
|
| `tick_resident.sh` | The resident loop: deploy → one tick under a timeout → sleep to the slot, one `afterany:self` successor, pause exits clean, shim changes resubmit the successor. |
|
|
13
13
|
| `requeue_moved_successors.sh` | Cancel pending same-name jobs that are no longer on the requested partition. The tick chain runs this before adding successors. |
|
|
14
14
|
| `sweep_git_locks.sh` | Remove stale `.git/*.lock` files from a checkout (older than N minutes, no live git process); the chain runs it before each deploy. |
|
|
15
|
-
| `install_codex.sh`, `install_hermes.sh` | Pin and install
|
|
15
|
+
| `install_claude.sh`, `install_codex.sh`, `install_hermes.sh` | Pin and install author/judge backends on the host. |
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Idempotent install of the harness-verified claude author binary.
|
|
3
|
+
#
|
|
4
|
+
# claude is a HOST prerequisite for the claude author backend (like uv, apptainer,
|
|
5
|
+
# and the .sif image) — deliberately NOT baked into the image, so it updates by
|
|
6
|
+
# swapping one host binary. Safe to run repeatedly: the fast path is a local
|
|
7
|
+
# `claude --version`, so it only touches the network on a version mismatch or a
|
|
8
|
+
# missing binary. Run at host setup, or best-effort from the tick chain.
|
|
9
|
+
#
|
|
10
|
+
# Usage: install_claude.sh [target_path]
|
|
11
|
+
# target_path where to place the binary
|
|
12
|
+
# (default: $OUTERLOOP_CLAUDE_BIN, else ~/.local/bin/claude)
|
|
13
|
+
set -euo pipefail
|
|
14
|
+
|
|
15
|
+
# Pinned release and per-platform SHA256. To bump WANT, hash the new binaries
|
|
16
|
+
# and update the pins together; downloaded bytes are verified before execution.
|
|
17
|
+
WANT="2.1.272"
|
|
18
|
+
TARGET="${1:-${OUTERLOOP_CLAUDE_BIN:-$HOME/.local/bin/claude}}"
|
|
19
|
+
|
|
20
|
+
have="$("$TARGET" --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 || true)"
|
|
21
|
+
if [ "$have" = "$WANT" ]; then
|
|
22
|
+
echo "install_claude: claude $WANT already at $TARGET"
|
|
23
|
+
exit 0
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
platform="$(uname -s)-$(uname -m)"
|
|
27
|
+
case "$platform" in
|
|
28
|
+
Linux-x86_64)
|
|
29
|
+
platform="linux-x64"
|
|
30
|
+
WANT_SHA256="d81396a668eb76fbddb49a2a5841f1b5d7af96b4c1f6500ced92f2c988f5bcd4"
|
|
31
|
+
if compgen -G '/lib/libc.musl-*' > /dev/null; then
|
|
32
|
+
platform="linux-x64-musl"
|
|
33
|
+
WANT_SHA256="e30bb3ac07c4f1c3f63b47312e9a73ba6875256b7768c4cdb784d2b179417489"
|
|
34
|
+
fi
|
|
35
|
+
;;
|
|
36
|
+
Linux-aarch64|Linux-arm64)
|
|
37
|
+
platform="linux-arm64"
|
|
38
|
+
WANT_SHA256="214a90efdd16ee0ea81132ffecced588dba394d178cc494f285ba04b5288c8de"
|
|
39
|
+
;;
|
|
40
|
+
*)
|
|
41
|
+
echo "install_claude: unsupported platform $platform (no sha256 pin)" >&2
|
|
42
|
+
exit 1
|
|
43
|
+
;;
|
|
44
|
+
esac
|
|
45
|
+
for tool in curl sha256sum; do
|
|
46
|
+
command -v "$tool" >/dev/null || {
|
|
47
|
+
echo "install_claude: required tool $tool is missing" >&2
|
|
48
|
+
exit 1
|
|
49
|
+
}
|
|
50
|
+
done
|
|
51
|
+
echo "install_claude: installing claude $WANT -> $TARGET (have '${have:-none}')"
|
|
52
|
+
url="https://downloads.claude.ai/claude-code-releases/$WANT/$platform/claude"
|
|
53
|
+
tmp="$(mktemp -d)"
|
|
54
|
+
staged="$TARGET.tmp.$$"
|
|
55
|
+
# clean BOTH the work dir and any staged binary on every exit, so a failed
|
|
56
|
+
# download/mv never leaves a stale temp next to the target
|
|
57
|
+
trap 'rm -rf "$tmp" "$staged"' EXIT
|
|
58
|
+
# bounded so a stalled download can't eat the tick's own walltime: this runs
|
|
59
|
+
# INSIDE the ~15-min tick job, so cap the fetch well under it (single attempt —
|
|
60
|
+
# a transient failure is retried by the next tick, since the install is idempotent)
|
|
61
|
+
curl -fsSL --connect-timeout 15 --max-time 120 --retry 0 "$url" -o "$tmp/claude"
|
|
62
|
+
# INTEGRITY GATE: verify the binary against the pin BEFORE installing or
|
|
63
|
+
# executing anything from it.
|
|
64
|
+
got_sha=$(sha256sum "$tmp/claude" | cut -d' ' -f1)
|
|
65
|
+
if [ "$got_sha" != "$WANT_SHA256" ]; then
|
|
66
|
+
echo "install_claude: sha256 mismatch (got $got_sha, want $WANT_SHA256) — refusing" >&2
|
|
67
|
+
exit 1
|
|
68
|
+
fi
|
|
69
|
+
# the target dir must exist BEFORE staging into it (the staged temp lives beside
|
|
70
|
+
# TARGET so the final mv is atomic on the same filesystem)
|
|
71
|
+
mkdir -p "$(dirname "$TARGET")"
|
|
72
|
+
install -m 0755 "$tmp/claude" "$staged"
|
|
73
|
+
# secondary sanity (integrity is already the sha256 gate above, so this runs
|
|
74
|
+
# VERIFIED bytes): the staged binary reports the pinned version before the mv
|
|
75
|
+
got="$("$staged" --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 || true)"
|
|
76
|
+
if [ "$got" != "$WANT" ]; then
|
|
77
|
+
echo "install_claude: downloaded claude reports '$got', wanted '$WANT' — not installing" >&2
|
|
78
|
+
exit 1
|
|
79
|
+
fi
|
|
80
|
+
# atomic replace on the same filesystem: never leave a half-written binary
|
|
81
|
+
mv -f "$staged" "$TARGET"
|
|
82
|
+
echo "install_claude: installed claude $got at $TARGET"
|
|
@@ -52,6 +52,8 @@ done
|
|
|
52
52
|
# partition may be a comma-list like "a,b"), pass them through.
|
|
53
53
|
acct_arg=""
|
|
54
54
|
[ -n "${OUTERLOOP_ACCOUNT:-}" ] && acct_arg="--account=${OUTERLOOP_ACCOUNT}"
|
|
55
|
+
qos_arg=""
|
|
56
|
+
[ -n "${OUTERLOOP_QOS:-}" ] && qos_arg="--qos=${OUTERLOOP_QOS}"
|
|
55
57
|
part_arg=""
|
|
56
58
|
[ -n "${OUTERLOOP_PARTITION:-}" ] && part_arg="--partition=${OUTERLOOP_PARTITION}"
|
|
57
59
|
|
|
@@ -104,7 +106,7 @@ while [ "$i" -le "$need" ]; do
|
|
|
104
106
|
|| date -r "$begin_epoch" +%Y-%m-%dT%H:%M:%S)
|
|
105
107
|
for attempt in 1 2 3; do
|
|
106
108
|
if sbatch --dependency=singleton --begin="$begin" \
|
|
107
|
-
${acct_arg:+"$acct_arg"} ${part_arg:+"$part_arg"} \
|
|
109
|
+
${acct_arg:+"$acct_arg"} ${part_arg:+"$part_arg"} ${qos_arg:+"$qos_arg"} \
|
|
108
110
|
"${OUTERLOOP_HOME:-}/scripts/tick_chain.sbatch"; then
|
|
109
111
|
break
|
|
110
112
|
fi
|
|
@@ -195,6 +195,7 @@ if [ -n "$ENV_TRUSTED" ]; then
|
|
|
195
195
|
OUTERLOOP_TARGET \
|
|
196
196
|
OUTERLOOP_GITHUB_APP_FILE OUTERLOOP_BOT_LOGIN OUTERLOOP_BOT_ALIASES \
|
|
197
197
|
OUTERLOOP_GPU_PARTITION OUTERLOOP_GPU_ACCOUNT \
|
|
198
|
+
OUTERLOOP_QOS OUTERLOOP_APPTAINER_BIN \
|
|
198
199
|
OUTERLOOP_IMAGE \
|
|
199
200
|
OUTERLOOP_PANEL OUTERLOOP_PANEL_KEY_FILE \
|
|
200
201
|
OUTERLOOP_PANEL_CODEX_KEY_FILE \
|
|
@@ -212,6 +213,28 @@ if [ -n "$ENV_TRUSTED" ]; then
|
|
|
212
213
|
done
|
|
213
214
|
fi
|
|
214
215
|
|
|
216
|
+
# The configured author's CLI is a host prerequisite (pinned installers under
|
|
217
|
+
# scripts/); provision it when missing. Best-effort: a failure here must never
|
|
218
|
+
# break the chain — start's preflight and the climb report a missing CLI.
|
|
219
|
+
case "${OUTERLOOP_AUTHOR_BACKEND:-claude}" in
|
|
220
|
+
claude)
|
|
221
|
+
# a recorded path is the one the jobs will use, so it alone decides;
|
|
222
|
+
# otherwise an absolute PATH hit or the default install location counts
|
|
223
|
+
# (jobs ignore relative PATH entries, so the check does too)
|
|
224
|
+
if [ -n "${OUTERLOOP_CLAUDE_BIN:-}" ]; then
|
|
225
|
+
target="$OUTERLOOP_CLAUDE_BIN"; found=""
|
|
226
|
+
[ -x "$target" ] && found="$target"
|
|
227
|
+
else
|
|
228
|
+
target="$HOME/.local/bin/claude"
|
|
229
|
+
found="$(command -v claude 2>/dev/null || true)"
|
|
230
|
+
case "$found" in /*) ;; *) found="" ;; esac
|
|
231
|
+
[ -z "$found" ] && [ -x "$target" ] && found="$target"
|
|
232
|
+
fi
|
|
233
|
+
if [ -z "$found" ]; then
|
|
234
|
+
bash "$OUTERLOOP_HOME/scripts/install_claude.sh" "$target" || echo "deploy: claude install failed"
|
|
235
|
+
fi
|
|
236
|
+
;;
|
|
237
|
+
esac
|
|
215
238
|
# The codex author binary is a host prerequisite; install it (idempotent, fast
|
|
216
239
|
# path is a local version check) when ANY codex role is deployed — the fleet
|
|
217
240
|
# author, or a codex panel lens (a claude-author/codex-panel rollout still
|
|
@@ -45,13 +45,15 @@ submit_successor() {
|
|
|
45
45
|
# them only when set.
|
|
46
46
|
local acct_arg=""
|
|
47
47
|
[ -n "${OUTERLOOP_ACCOUNT:-}" ] && acct_arg="--account=${OUTERLOOP_ACCOUNT}"
|
|
48
|
+
local qos_arg=""
|
|
49
|
+
[ -n "${OUTERLOOP_QOS:-}" ] && qos_arg="--qos=${OUTERLOOP_QOS}"
|
|
48
50
|
local part_arg=""
|
|
49
51
|
[ -n "${OUTERLOOP_PARTITION:-}" ] && part_arg="--partition=${OUTERLOOP_PARTITION}"
|
|
50
52
|
local out="" attempt
|
|
51
53
|
for attempt in 1 2 3; do
|
|
52
54
|
if out=$(sbatch --parsable --dependency="$dep" --time="$resident_minutes" \
|
|
53
55
|
--job-name="$RESIDENT_JOB_NAME" --export=ALL \
|
|
54
|
-
${acct_arg:+"$acct_arg"} ${part_arg:+"$part_arg"} \
|
|
56
|
+
${acct_arg:+"$acct_arg"} ${part_arg:+"$part_arg"} ${qos_arg:+"$qos_arg"} \
|
|
55
57
|
"$shim" 2>/dev/null); then
|
|
56
58
|
printf '%s' "${out%%;*}"
|
|
57
59
|
return 0
|