deeploop 0.1.2__tar.gz → 0.1.4__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.
- {deeploop-0.1.2/src/deeploop.egg-info → deeploop-0.1.4}/PKG-INFO +29 -13
- {deeploop-0.1.2 → deeploop-0.1.4}/README.md +28 -12
- {deeploop-0.1.2 → deeploop-0.1.4}/configs/runtime/provider-selection-registry.yaml +4 -1
- {deeploop-0.1.2 → deeploop-0.1.4}/configs/runtime/provider-setup-registry.yaml +2 -2
- {deeploop-0.1.2 → deeploop-0.1.4}/pyproject.toml +1 -1
- {deeploop-0.1.2 → deeploop-0.1.4}/scripts/runtime/invoke_provider_prompt.py +27 -4
- deeploop-0.1.4/src/deeploop/__init__.py +1 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/artifacts/artifact_packager.py +37 -1
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/cli/init_mission.py +23 -1
- deeploop-0.1.4/src/deeploop/cli/run_project.py +165 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/mission/_operator_surface.py +8 -8
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/mission/mission_discovery.py +160 -16
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/mission/mission_management.py +28 -15
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/mission/mission_runtime.py +3 -5
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/mission/orchestrator.py +2 -96
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/mission/project_bootstrap.py +301 -1
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/mission/project_runner.py +57 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/project_contract.py +4 -0
- deeploop-0.1.4/src/deeploop/runtime/openai_compatible_adapter.py +167 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/runtime/provider_launcher.py +312 -51
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/runtime/recursive_agent_runtime.py +212 -21
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/testing/test_tiers.py +4 -0
- {deeploop-0.1.2 → deeploop-0.1.4/src/deeploop.egg-info}/PKG-INFO +29 -13
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop.egg-info/SOURCES.txt +2 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/tests/test_artifact_packager.py +104 -0
- deeploop-0.1.4/tests/test_end_to_end_smoke.py +386 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/tests/test_mission_discovery.py +62 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/tests/test_mission_management.py +10 -10
- {deeploop-0.1.2 → deeploop-0.1.4}/tests/test_mission_monitor.py +10 -10
- {deeploop-0.1.2 → deeploop-0.1.4}/tests/test_mission_runtime.py +22 -3
- deeploop-0.1.4/tests/test_openai_compatible_adapter.py +70 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/tests/test_package_structure.py +45 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/tests/test_project_contract.py +69 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/tests/test_project_runner.py +186 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/tests/test_provider_launcher.py +162 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/tests/test_public_bootstrap.py +2 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/tests/test_recursive_agent_runtime.py +281 -2
- deeploop-0.1.4/tests/test_release_docker_validation.py +132 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/tests/test_repo_contract.py +3 -2
- {deeploop-0.1.2 → deeploop-0.1.4}/tests/test_test_tiers.py +12 -0
- deeploop-0.1.2/src/deeploop/__init__.py +0 -1
- deeploop-0.1.2/src/deeploop/cli/run_project.py +0 -59
- deeploop-0.1.2/tests/test_end_to_end_smoke.py +0 -135
- deeploop-0.1.2/tests/test_release_docker_validation.py +0 -70
- {deeploop-0.1.2 → deeploop-0.1.4}/LICENSE +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/MANIFEST.in +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/configs/autonomy/confound-guard.yaml +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/configs/autonomy/evidence-policy.yaml +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/configs/autonomy/fresh-context-redteam.yaml +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/configs/autonomy/gates.yaml +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/configs/autonomy/mission-outer-loop.yaml +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/configs/autonomy/novelty-refresh.yaml +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/configs/autonomy/operator-boundaries.yaml +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/configs/autonomy/research-sanity-gates.yaml +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/configs/autonomy/self-correction.yaml +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/configs/autonomy/self-optimization.yaml +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/configs/autonomy/state-machine.yaml +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/configs/autonomy/statistical-rigor.yaml +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/configs/autonomy/utility-scorer.yaml +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/configs/evaluation/statistical-rigor.yaml +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/configs/evaluation/system-metrics.yaml +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/configs/execution-profiles/inference-families.yaml +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/configs/execution-profiles/training-presets.yaml +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/configs/ledger/policy.yaml +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/configs/manifests/run-manifest-template.json +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/configs/memory/registry.yaml +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/configs/operating-model/modes.yaml +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/configs/platform/expansion.yaml +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/configs/policy/placement.yaml +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/configs/resource-tiers/tiers.yaml +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/configs/roles/agent-roles.yaml +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/configs/runtime/artifact-package-contract.yaml +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/configs/runtime/backend-policy.yaml +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/configs/runtime/mission-package.yaml +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/configs/runtime/mission-scheduler.yaml +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/configs/runtime/recovery-policy.yaml +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/configs/runtime/recursive-agent-runtime-provider.example.yaml +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/configs/runtime/recursive-agent-runtime.yaml +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/configs/runtime/release-candidate-policy.yaml +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/configs/runtime/self-healing-runtime.yaml +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/configs/runtime/stage-kernel-registry.yaml +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/configs/runtime/substrate-boundary.yaml +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/configs/runtime/translation-long-run-baseline-queue.yaml +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/configs/sandbox/agent-launch-policy.yaml +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/schemas/agent-handoff.schema.json +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/schemas/confound-guard-report.schema.json +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/schemas/ledger-entry.schema.json +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/schemas/mission-acceptance-criteria.schema.json +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/schemas/mission-action.schema.json +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/schemas/mission-artifact-package.schema.json +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/schemas/mission-branch-record.schema.json +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/schemas/mission-decision.schema.json +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/schemas/mission-meta-eval.schema.json +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/schemas/mission-operator-request.schema.json +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/schemas/mission-state.schema.json +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/schemas/recursive-agent-result.schema.json +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/schemas/release-candidate-review.schema.json +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/schemas/research-memory-entry.schema.json +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/schemas/research-sanity-report.schema.json +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/schemas/run-manifest.schema.json +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/schemas/self-correction-report.schema.json +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/scripts/mission/init_mission.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/scripts/mission/manage_mission.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/scripts/mission/monitor_mission.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/scripts/mission/package_mission.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/scripts/mission/record_finding.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/scripts/mission/run_confound_guard.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/scripts/mission/run_fresh_context_redteam.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/scripts/mission/run_mission.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/scripts/mission/run_mission_scheduler.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/scripts/mission/run_novelty_refresh.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/scripts/mission/run_project.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/scripts/mission/run_recursive_agent_loop.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/scripts/mission/run_self_correction.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/scripts/mission/run_self_optimization.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/scripts/mission/run_statistical_rigor.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/scripts/mission/run_utility_scorer.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/scripts/runtime/run_confound_guard.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/scripts/runtime/run_queue.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/scripts/runtime/run_recoverable_stage.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/scripts/runtime/run_sanity_gate.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/scripts/runtime/run_stage_kernel.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/scripts/runtime/run_statistical_rigor.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/setup.cfg +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/_build.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/artifacts/__init__.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/artifacts/mission_package.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/artifacts/release_automation.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/artifacts/submission_export.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/autonomy/__init__.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/autonomy/gate_taxonomy.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/autonomy/mission_autonomy.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/autonomy/mission_contract_snapshot.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/autonomy/operating_modes.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/autonomy/operator_inbox.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/cli/__init__.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/cli/analyze.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/cli/export_mission.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/cli/package_mission.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/core/__init__.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/core/config_paths.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/core/dotted.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/core/ledger.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/core/paths.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/core/phase_defaults.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/core/structured_io.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/fresh_context_redteam.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/mission/__init__.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/mission/_autonomy_gap_telemetry.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/mission/_constants.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/mission/_monitor_classification.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/mission/_monitor_render.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/mission/_monitor_snapshot.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/mission/_runtime_contract.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/mission/_runtime_persistence.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/mission/mission_acceptance.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/mission/mission_decision_engine.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/mission/mission_memory.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/mission/mission_monitor.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/mission/mission_progress.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/mission/mission_scheduler.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/mission/mission_state.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/mission/plain_folder_followup.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/platform/__init__.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/platform/contracts.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/research/__init__.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/research/confound_guard.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/research/indexed_memory.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/research/novelty_refresh.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/research/sanity_gates.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/research/self_correction.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/research/self_optimization.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/research/statistical_rigor.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/research/utility_scorer.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/runtime/__init__.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/runtime/_prompt_renderer.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/runtime/_stage_kernel_registry.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/runtime/_stage_kernel_reporting.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/runtime/_stage_kernel_resolution.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/runtime/adaptation_training_runtime.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/runtime/copilot_adapter.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/runtime/metric_ratchets.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/runtime/mission_executor_registry.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/runtime/plain_folder_adapter.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/runtime/runtime_recovery.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/runtime/sandbox.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/runtime/self_healing_runtime.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/runtime/stage_kernels.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/testing/__init__.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/testing/acceptance_campaigns.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/testing/plain_folder_proof_matrix.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop/testing/proof_matrix_reviews.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop.egg-info/dependency_links.txt +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop.egg-info/entry_points.txt +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop.egg-info/requires.txt +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/src/deeploop.egg-info/top_level.txt +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/tests/test_acceptance_campaigns.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/tests/test_adaptation_training_runtime.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/tests/test_confound_guard.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/tests/test_core_paths.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/tests/test_fresh_context_redteam.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/tests/test_indexed_research_memory.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/tests/test_metric_ratchets.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/tests/test_mission_autonomy.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/tests/test_mission_decision_engine.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/tests/test_mission_executor_registry.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/tests/test_mission_package.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/tests/test_mission_scheduler.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/tests/test_mission_state.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/tests/test_novelty_refresh.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/tests/test_plain_folder_proof_matrix.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/tests/test_platform_integration.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/tests/test_proof_matrix_reviews.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/tests/test_record_finding.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/tests/test_release_automation.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/tests/test_runtime_recovery.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/tests/test_sandbox.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/tests/test_self_correction.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/tests/test_self_healing_runtime.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/tests/test_self_optimization.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/tests/test_stage_kernels.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/tests/test_statistical_rigor.py +0 -0
- {deeploop-0.1.2 → deeploop-0.1.4}/tests/test_utility_scorer.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: deeploop
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.4
|
|
4
4
|
Summary: DeepLoop autonomous research autopilot control plane.
|
|
5
5
|
Author: DeepLoop maintainers
|
|
6
6
|
License-Expression: MIT
|
|
@@ -93,26 +93,35 @@ DeepLoop **owns behavior** and orchestration; substrate repos own reusable domai
|
|
|
93
93
|
cp -R examples/translation-budget-ladder PROJECT_FOLDER
|
|
94
94
|
```
|
|
95
95
|
|
|
96
|
-
|
|
96
|
+
- fastest path:
|
|
97
97
|
|
|
98
98
|
```text
|
|
99
99
|
deeploop run --project-root examples/translation-budget-ladder --until-complete
|
|
100
100
|
```
|
|
101
101
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
102
|
+
> **Note:** If `<project-folder>/.deeploop/missions/*.yaml` files exist, `deeploop run`
|
|
103
|
+
> automatically uses the first one instead of bootstrapping a blank mission.
|
|
104
|
+
> For a plain folder with no existing config, it bootstraps from the folder's facts.
|
|
105
|
+
> If the folder is rough but still recognizable, DeepLoop can initialize with
|
|
106
|
+
> disclosed clarifications/defaults and keep the project folder unchanged. To
|
|
107
|
+
> target a specific explicit config directly, use `deeploop init --config
|
|
108
|
+
> <mission-config.yaml>` followed by `deeploop start --mission-state
|
|
109
|
+
> <mission-state.json>`.
|
|
108
110
|
|
|
109
|
-
|
|
111
|
+
- discovery / operator path:
|
|
110
112
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
113
|
+
```text
|
|
114
|
+
deeploop init --project-root PROJECT_FOLDER --force
|
|
115
|
+
deeploop init --discover --project-root PROJECT_FOLDER --force
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Use plain `deeploop init --project-root ...` when the folder is rough but
|
|
119
|
+
already recognizable. Add `--discover` when you want DeepLoop to ask
|
|
120
|
+
clarifying questions before kickoff.
|
|
114
121
|
|
|
115
|
-
|
|
122
|
+
On a copied folder, substitute `PROJECT_FOLDER` in the commands above. If
|
|
123
|
+
DeepLoop cannot safely bootstrap the folder yet, it stops with bounded
|
|
124
|
+
bootstrap-repair guidance instead of mutating the project.
|
|
116
125
|
|
|
117
126
|
5. **Use the operator CLI when a run pauses**
|
|
118
127
|
|
|
@@ -124,6 +133,13 @@ DeepLoop **owns behavior** and orchestration; substrate repos own reusable domai
|
|
|
124
133
|
|
|
125
134
|
The `deeploop` CLI is the single entry point — `run`, `init`, `status`, `inbox`, `resume`, and more are all subcommands.
|
|
126
135
|
|
|
136
|
+
## Readiness at a glance
|
|
137
|
+
|
|
138
|
+
- **Fastest supported path:** Linux, Python 3.11+, `pip install deeploop`, `make setup`, `make public-bootstrap-check`, then `deeploop run --project-root <project-folder> --until-complete`
|
|
139
|
+
- **Messy starts are supported:** rough plain-folder projects can initialize with disclosed clarifications/defaults, or you can use `deeploop init --discover ...` for a guided kickoff
|
|
140
|
+
- **Repair stays bounded:** if the folder is missing the plain-folder bootstrap contract, DeepLoop exits with bootstrap-repair guidance and suggested starter inputs instead of silently rewriting project files
|
|
141
|
+
- **Current release gate:** `make public-bootstrap-check`, `make docker-release-validate`, and `make docs-build`, with PyPI publish only from a published GitHub Release whose tag matches `project.version`
|
|
142
|
+
|
|
127
143
|
## Best fit today
|
|
128
144
|
|
|
129
145
|
DeepLoop is best when you already have:
|
|
@@ -54,26 +54,35 @@ DeepLoop **owns behavior** and orchestration; substrate repos own reusable domai
|
|
|
54
54
|
cp -R examples/translation-budget-ladder PROJECT_FOLDER
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
- fastest path:
|
|
58
58
|
|
|
59
59
|
```text
|
|
60
60
|
deeploop run --project-root examples/translation-budget-ladder --until-complete
|
|
61
61
|
```
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
63
|
+
> **Note:** If `<project-folder>/.deeploop/missions/*.yaml` files exist, `deeploop run`
|
|
64
|
+
> automatically uses the first one instead of bootstrapping a blank mission.
|
|
65
|
+
> For a plain folder with no existing config, it bootstraps from the folder's facts.
|
|
66
|
+
> If the folder is rough but still recognizable, DeepLoop can initialize with
|
|
67
|
+
> disclosed clarifications/defaults and keep the project folder unchanged. To
|
|
68
|
+
> target a specific explicit config directly, use `deeploop init --config
|
|
69
|
+
> <mission-config.yaml>` followed by `deeploop start --mission-state
|
|
70
|
+
> <mission-state.json>`.
|
|
69
71
|
|
|
70
|
-
|
|
72
|
+
- discovery / operator path:
|
|
71
73
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
74
|
+
```text
|
|
75
|
+
deeploop init --project-root PROJECT_FOLDER --force
|
|
76
|
+
deeploop init --discover --project-root PROJECT_FOLDER --force
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Use plain `deeploop init --project-root ...` when the folder is rough but
|
|
80
|
+
already recognizable. Add `--discover` when you want DeepLoop to ask
|
|
81
|
+
clarifying questions before kickoff.
|
|
75
82
|
|
|
76
|
-
|
|
83
|
+
On a copied folder, substitute `PROJECT_FOLDER` in the commands above. If
|
|
84
|
+
DeepLoop cannot safely bootstrap the folder yet, it stops with bounded
|
|
85
|
+
bootstrap-repair guidance instead of mutating the project.
|
|
77
86
|
|
|
78
87
|
5. **Use the operator CLI when a run pauses**
|
|
79
88
|
|
|
@@ -85,6 +94,13 @@ DeepLoop **owns behavior** and orchestration; substrate repos own reusable domai
|
|
|
85
94
|
|
|
86
95
|
The `deeploop` CLI is the single entry point — `run`, `init`, `status`, `inbox`, `resume`, and more are all subcommands.
|
|
87
96
|
|
|
97
|
+
## Readiness at a glance
|
|
98
|
+
|
|
99
|
+
- **Fastest supported path:** Linux, Python 3.11+, `pip install deeploop`, `make setup`, `make public-bootstrap-check`, then `deeploop run --project-root <project-folder> --until-complete`
|
|
100
|
+
- **Messy starts are supported:** rough plain-folder projects can initialize with disclosed clarifications/defaults, or you can use `deeploop init --discover ...` for a guided kickoff
|
|
101
|
+
- **Repair stays bounded:** if the folder is missing the plain-folder bootstrap contract, DeepLoop exits with bootstrap-repair guidance and suggested starter inputs instead of silently rewriting project files
|
|
102
|
+
- **Current release gate:** `make public-bootstrap-check`, `make docker-release-validate`, and `make docs-build`, with PyPI publish only from a published GitHub Release whose tag matches `project.version`
|
|
103
|
+
|
|
88
104
|
## Best fit today
|
|
89
105
|
|
|
90
106
|
DeepLoop is best when you already have:
|
|
@@ -112,7 +112,7 @@ selection_profiles:
|
|
|
112
112
|
- vllm
|
|
113
113
|
- local-transformers
|
|
114
114
|
openai-compatible-api-control-plane:
|
|
115
|
-
status:
|
|
115
|
+
status: implemented
|
|
116
116
|
provider_family: openai-compatible-api
|
|
117
117
|
backend: openai-compatible-api
|
|
118
118
|
model_selection:
|
|
@@ -125,6 +125,9 @@ selection_profiles:
|
|
|
125
125
|
provider_family_switch: explicit-only
|
|
126
126
|
backend_switch: provider-native
|
|
127
127
|
model_fallback: explicit-model-ladder-only
|
|
128
|
+
notes:
|
|
129
|
+
- runtime support currently covers prompt/result control-plane flows that return structured JSON
|
|
130
|
+
- recursive-agent tool execution remains on the copilot-cli path
|
|
128
131
|
anthropic-api-control-plane:
|
|
129
132
|
status: reserved-runtime-adapter
|
|
130
133
|
provider_family: anthropic-api
|
|
@@ -50,7 +50,7 @@ provider_families:
|
|
|
50
50
|
openai-compatible-api:
|
|
51
51
|
display_name: OpenAI-compatible API providers
|
|
52
52
|
public_contract_tier: first-class
|
|
53
|
-
runtime_integration:
|
|
53
|
+
runtime_integration: implemented
|
|
54
54
|
required_tools:
|
|
55
55
|
- command: python
|
|
56
56
|
purpose: control-plane entrypoint
|
|
@@ -71,7 +71,7 @@ provider_families:
|
|
|
71
71
|
expectation: set in the operator shell or runner environment
|
|
72
72
|
manual:
|
|
73
73
|
- if OPENAI_BASE_URL is set, confirm the endpoint is reachable over HTTPS
|
|
74
|
-
-
|
|
74
|
+
- the public adapter currently covers prompt/result control-plane flows; it does not add Copilot-style tool execution
|
|
75
75
|
anthropic-api:
|
|
76
76
|
display_name: Anthropic API providers
|
|
77
77
|
public_contract_tier: first-class
|
|
@@ -1,13 +1,36 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import argparse
|
|
4
|
+
import os
|
|
4
5
|
import sys
|
|
5
6
|
from pathlib import Path
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
SCRIPT_PATH = Path(__file__).resolve()
|
|
9
|
+
REPO_ROOT = SCRIPT_PATH.parents[2]
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _bootstrap_import_path() -> None:
|
|
13
|
+
candidates: list[Path] = []
|
|
14
|
+
|
|
15
|
+
cache_src = os.environ.get("DEEPLOOP_RUNTIME_CACHE_SRC", "").strip()
|
|
16
|
+
if cache_src:
|
|
17
|
+
candidates.append(Path(cache_src).expanduser().resolve())
|
|
18
|
+
|
|
19
|
+
repo_src = REPO_ROOT / "src"
|
|
20
|
+
if repo_src.is_dir():
|
|
21
|
+
candidates.append(repo_src)
|
|
22
|
+
|
|
23
|
+
package_root = SCRIPT_PATH.parents[3]
|
|
24
|
+
if package_root.name == "deeploop" and (package_root / "__init__.py").is_file():
|
|
25
|
+
candidates.append(package_root.parent)
|
|
26
|
+
|
|
27
|
+
for candidate in candidates:
|
|
28
|
+
candidate_text = str(candidate)
|
|
29
|
+
if candidate.is_dir() and candidate_text not in sys.path:
|
|
30
|
+
sys.path.insert(0, candidate_text)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
_bootstrap_import_path()
|
|
11
34
|
|
|
12
35
|
from deeploop.runtime.provider_launcher import run_provider_prompt
|
|
13
36
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.4"
|
|
@@ -850,6 +850,39 @@ def _artifact_bullets(artifacts: list[dict[str, Any]], artifact_ids: list[str],
|
|
|
850
850
|
return bullets
|
|
851
851
|
|
|
852
852
|
|
|
853
|
+
def _mission_runtime_handoff_bullets(mission_state: dict[str, Any], *, ledger_entries: int) -> list[str]:
|
|
854
|
+
mission_runtime = mission_state.get("mission_runtime") if isinstance(mission_state.get("mission_runtime"), dict) else {}
|
|
855
|
+
if not mission_runtime:
|
|
856
|
+
return [f"Ledger entries captured: {ledger_entries}."]
|
|
857
|
+
bullets = [
|
|
858
|
+
"Mission runtime: "
|
|
859
|
+
f"{mission_runtime.get('status', 'unknown')} after "
|
|
860
|
+
f"{int(mission_runtime.get('iterations_completed', 0) or 0)} bounded iteration(s)."
|
|
861
|
+
]
|
|
862
|
+
telemetry = (
|
|
863
|
+
mission_runtime.get("autonomy_gap_telemetry")
|
|
864
|
+
if isinstance(mission_runtime.get("autonomy_gap_telemetry"), dict)
|
|
865
|
+
else {}
|
|
866
|
+
)
|
|
867
|
+
counts = telemetry.get("counts") if isinstance(telemetry.get("counts"), dict) else {}
|
|
868
|
+
if counts:
|
|
869
|
+
bullets.append(
|
|
870
|
+
"Recovery telemetry: "
|
|
871
|
+
f"soft_gates={int(counts.get('soft_gates_total', 0) or 0)}, "
|
|
872
|
+
f"bounded_recoveries={int(counts.get('bounded_recovery_outcomes', 0) or 0)}, "
|
|
873
|
+
f"operator_requests={int(counts.get('operator_requests_total', 0) or 0)}."
|
|
874
|
+
)
|
|
875
|
+
auto_recovered = int(counts.get("temporary_gap_auto_recovered", 0) or 0)
|
|
876
|
+
escalated = int(counts.get("temporary_gap_escalated", 0) or 0)
|
|
877
|
+
if auto_recovered or escalated:
|
|
878
|
+
bullets.append(
|
|
879
|
+
"Temporary gaps: "
|
|
880
|
+
f"auto_recovered={auto_recovered}, escalated={escalated}."
|
|
881
|
+
)
|
|
882
|
+
bullets.append(f"Ledger entries captured: {ledger_entries}.")
|
|
883
|
+
return bullets
|
|
884
|
+
|
|
885
|
+
|
|
853
886
|
def _data_artifact_reference_only(metadata: dict[str, Any]) -> bool:
|
|
854
887
|
return metadata.get("package") is False or str(
|
|
855
888
|
metadata.get("packaging_policy") or metadata.get("package_policy") or ""
|
|
@@ -1155,9 +1188,11 @@ def package_mission_artifacts(
|
|
|
1155
1188
|
register_artifact(report_path, category=category, metadata=metadata)
|
|
1156
1189
|
|
|
1157
1190
|
ledger_path = mission_root / "ledger.jsonl"
|
|
1191
|
+
ledger_entries: list[dict[str, Any]] = []
|
|
1158
1192
|
if ledger_path.exists():
|
|
1159
1193
|
ledger_artifact_id = register_artifact(ledger_path, category="ledgers")
|
|
1160
|
-
|
|
1194
|
+
ledger_entries = _load_jsonl(ledger_path)
|
|
1195
|
+
for entry in ledger_entries:
|
|
1161
1196
|
related_paths = entry.get("related_paths", [])
|
|
1162
1197
|
for raw_path in related_paths:
|
|
1163
1198
|
if not isinstance(raw_path, str):
|
|
@@ -1382,6 +1417,7 @@ def package_mission_artifacts(
|
|
|
1382
1417
|
f"Current phase: {mission_state.get('current_phase')} ({mission_state.get('status')})",
|
|
1383
1418
|
f"Packaged {len(artifacts)} artifacts across {len(run_bundles)} manifest bundles.",
|
|
1384
1419
|
]
|
|
1420
|
+
operator_bullets.extend(_mission_runtime_handoff_bullets(mission_state, ledger_entries=len(ledger_entries)))
|
|
1385
1421
|
if missing_required_artifacts_summary:
|
|
1386
1422
|
operator_bullets.append(missing_required_artifacts_summary)
|
|
1387
1423
|
next_actions = mission_state.get("next_actions", {})
|
|
@@ -8,7 +8,11 @@ from deeploop.core.paths import SCRATCH_DIR, WORKSPACE_ROOT, WORKSPACE_ROOT_ENV_
|
|
|
8
8
|
from deeploop.core.structured_io import write_text, write_yaml_mapping
|
|
9
9
|
from deeploop.mission.mission_discovery import run_interactive_discovery
|
|
10
10
|
from deeploop.mission.orchestrator import initialize_mission
|
|
11
|
-
from deeploop.mission.project_bootstrap import
|
|
11
|
+
from deeploop.mission.project_bootstrap import (
|
|
12
|
+
build_mission_config_from_project_root,
|
|
13
|
+
render_bootstrap_repair_lines,
|
|
14
|
+
render_mission_contract_summary_lines,
|
|
15
|
+
)
|
|
12
16
|
|
|
13
17
|
|
|
14
18
|
def _add_init_args(parser: argparse.ArgumentParser) -> None:
|
|
@@ -31,6 +35,14 @@ def _add_init_args(parser: argparse.ArgumentParser) -> None:
|
|
|
31
35
|
parser.add_argument("--force", action="store_true", help="Replace any existing mission root with the same mission id.")
|
|
32
36
|
|
|
33
37
|
|
|
38
|
+
def _print_readiness_summary(config: dict[str, object]) -> None:
|
|
39
|
+
mission_contract = config.get("mission_contract") if isinstance(config.get("mission_contract"), dict) else {}
|
|
40
|
+
if not mission_contract:
|
|
41
|
+
return
|
|
42
|
+
for line in render_mission_contract_summary_lines(mission_contract, format="plain"):
|
|
43
|
+
print(f"mission-init: {line}" if line else "mission-init:")
|
|
44
|
+
|
|
45
|
+
|
|
34
46
|
def _init_mission(args: argparse.Namespace) -> int:
|
|
35
47
|
has_config = bool(getattr(args, "config", None))
|
|
36
48
|
has_project_root = bool(getattr(args, "project_root", None))
|
|
@@ -75,9 +87,18 @@ def _init_mission(args: argparse.Namespace) -> int:
|
|
|
75
87
|
write_text(persisted_config_path, Path(discovery["config_path"]).read_text(encoding="utf-8"))
|
|
76
88
|
print(f"mission-init: used confirmed discovery config {discovery['config_path']}")
|
|
77
89
|
print(f"mission-init: wrote generated config to {persisted_config_path}")
|
|
90
|
+
_print_readiness_summary(discovery["config"])
|
|
78
91
|
elif has_project_root:
|
|
79
92
|
project_root = Path(args.project_root).expanduser().resolve()
|
|
80
93
|
generated_config = build_mission_config_from_project_root(project_root, mission_id=getattr(args, "mission_id", None))
|
|
94
|
+
bootstrap_repair = (
|
|
95
|
+
generated_config.get("bootstrap_repair") if isinstance(generated_config.get("bootstrap_repair"), dict) else None
|
|
96
|
+
)
|
|
97
|
+
if isinstance(bootstrap_repair, dict) and str(bootstrap_repair.get("status") or "").strip().lower() == "required":
|
|
98
|
+
print(f"mission-init: project-root bootstrap needs repair for {project_root}", file=sys.stderr)
|
|
99
|
+
for line in render_bootstrap_repair_lines(bootstrap_repair, format="plain"):
|
|
100
|
+
print(f"mission-init: {line}" if line else "mission-init:", file=sys.stderr)
|
|
101
|
+
return 2
|
|
81
102
|
generated_config_dir = SCRATCH_DIR / "mission_bootstrap_configs"
|
|
82
103
|
generated_config_dir.mkdir(parents=True, exist_ok=True)
|
|
83
104
|
generated_config_path = generated_config_dir / f"{generated_config['mission']['id']}.yaml"
|
|
@@ -87,6 +108,7 @@ def _init_mission(args: argparse.Namespace) -> int:
|
|
|
87
108
|
write_text(persisted_config_path, generated_config_path.read_text(encoding="utf-8"))
|
|
88
109
|
print(f"mission-init: bootstrapped mission config from project folder {project_root}")
|
|
89
110
|
print(f"mission-init: wrote generated config to {persisted_config_path}")
|
|
111
|
+
_print_readiness_summary(generated_config)
|
|
90
112
|
else:
|
|
91
113
|
result = initialize_mission(Path(args.config).expanduser().resolve(), force=getattr(args, "force", False))
|
|
92
114
|
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import json
|
|
5
|
+
import sys
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
from deeploop.mission.project_bootstrap import render_bootstrap_repair_lines
|
|
10
|
+
from deeploop.mission.project_runner import _jsonify, run_project_until_complete
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _add_run_args(parser: argparse.ArgumentParser) -> None:
|
|
14
|
+
parser.add_argument(
|
|
15
|
+
"--project-root",
|
|
16
|
+
required=True,
|
|
17
|
+
help="Path to the plain researcher project folder. `deeploop run` bootstraps or reuses the mission state for you.",
|
|
18
|
+
)
|
|
19
|
+
parser.add_argument("--mission-id", help="Optional override for the generated mission id.")
|
|
20
|
+
parser.add_argument("--force", action="store_true", help="Replace any existing mission root with the same mission id.")
|
|
21
|
+
parser.add_argument(
|
|
22
|
+
"--until-complete",
|
|
23
|
+
action="store_true",
|
|
24
|
+
required=True,
|
|
25
|
+
help=(
|
|
26
|
+
"Keep extending bounded runtime passes until the mission completes or hits a true operator handoff. "
|
|
27
|
+
"Use `deeploop init` plus `deeploop start`/`deeploop resume` instead when you want manual control."
|
|
28
|
+
),
|
|
29
|
+
)
|
|
30
|
+
parser.add_argument(
|
|
31
|
+
"--chunk-iterations",
|
|
32
|
+
type=int,
|
|
33
|
+
default=8,
|
|
34
|
+
help="How many additional bounded mission-runtime iterations to grant per pass.",
|
|
35
|
+
)
|
|
36
|
+
parser.add_argument(
|
|
37
|
+
"--max-total-iterations",
|
|
38
|
+
type=int,
|
|
39
|
+
default=256,
|
|
40
|
+
help="Absolute mission-runtime iteration budget across the full `--until-complete` run.",
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _first_next_command(snapshot: dict[str, Any] | None) -> str | None:
|
|
45
|
+
if not isinstance(snapshot, dict):
|
|
46
|
+
return None
|
|
47
|
+
operator_console = snapshot.get("operator_console")
|
|
48
|
+
if not isinstance(operator_console, dict):
|
|
49
|
+
return None
|
|
50
|
+
next_commands = operator_console.get("next_commands")
|
|
51
|
+
if not isinstance(next_commands, list):
|
|
52
|
+
return None
|
|
53
|
+
for entry in next_commands:
|
|
54
|
+
if isinstance(entry, dict):
|
|
55
|
+
command = str(entry.get("command") or "").strip()
|
|
56
|
+
if command:
|
|
57
|
+
return command
|
|
58
|
+
return None
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _resume_summary_line(result: dict[str, Any]) -> str | None:
|
|
62
|
+
resume_summary = result.get("resume_summary")
|
|
63
|
+
if not isinstance(resume_summary, dict):
|
|
64
|
+
return None
|
|
65
|
+
parts: list[str] = []
|
|
66
|
+
if resume_summary.get("resumed_existing_mission"):
|
|
67
|
+
initial_iterations = int(resume_summary.get("initial_iterations_completed", 0) or 0)
|
|
68
|
+
initial_status = str(resume_summary.get("initial_runtime_status") or "unknown")
|
|
69
|
+
parts.append(f"reused prior mission state ({initial_iterations} recorded iteration(s), status `{initial_status}`)")
|
|
70
|
+
bounded_resume_passes = int(resume_summary.get("bounded_resume_passes", 0) or 0)
|
|
71
|
+
if bounded_resume_passes > 0:
|
|
72
|
+
parts.append(f"auto-resumed {bounded_resume_passes} bounded pass(es)")
|
|
73
|
+
soft_recovery_resume_passes = int(resume_summary.get("soft_recovery_resume_passes", 0) or 0)
|
|
74
|
+
if soft_recovery_resume_passes > 0:
|
|
75
|
+
parts.append(f"{soft_recovery_resume_passes} via soft-gate recovery")
|
|
76
|
+
if not parts:
|
|
77
|
+
return None
|
|
78
|
+
return "; ".join(parts)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def _noncompleted_summary_lines(result: dict[str, Any]) -> list[str]:
|
|
82
|
+
status = str(result.get("status") or "stopped")
|
|
83
|
+
bootstrap_repair = result.get("bootstrap_repair") if isinstance(result.get("bootstrap_repair"), dict) else None
|
|
84
|
+
if status == "bootstrap-repair-required" and isinstance(bootstrap_repair, dict):
|
|
85
|
+
return [
|
|
86
|
+
"DeepLoop could not bootstrap this project root yet.",
|
|
87
|
+
f"- outcome: `{status}`",
|
|
88
|
+
*render_bootstrap_repair_lines(bootstrap_repair, format="plain"),
|
|
89
|
+
]
|
|
90
|
+
snapshot = result.get("snapshot") if isinstance(result.get("snapshot"), dict) else None
|
|
91
|
+
operator_console = snapshot.get("operator_console") if isinstance(snapshot, dict) else None
|
|
92
|
+
headline = (
|
|
93
|
+
str(operator_console.get("headline") or "").strip()
|
|
94
|
+
if isinstance(operator_console, dict)
|
|
95
|
+
else ""
|
|
96
|
+
)
|
|
97
|
+
summary = (
|
|
98
|
+
str(operator_console.get("summary") or "").strip()
|
|
99
|
+
if isinstance(operator_console, dict)
|
|
100
|
+
else ""
|
|
101
|
+
)
|
|
102
|
+
recommendation = (
|
|
103
|
+
str(operator_console.get("recommendation") or "").strip()
|
|
104
|
+
if isinstance(operator_console, dict)
|
|
105
|
+
else ""
|
|
106
|
+
)
|
|
107
|
+
mission_state_path = result.get("mission_state_path")
|
|
108
|
+
next_command = _first_next_command(snapshot)
|
|
109
|
+
lines = [
|
|
110
|
+
"DeepLoop did not complete this run.",
|
|
111
|
+
f"- outcome: `{status}`",
|
|
112
|
+
]
|
|
113
|
+
if headline:
|
|
114
|
+
lines.append(f"- handoff: {headline}")
|
|
115
|
+
if summary:
|
|
116
|
+
lines.append(f"- summary: {summary}")
|
|
117
|
+
elif status == "max-total-iterations":
|
|
118
|
+
lines.append("- summary: Reached the total `--max-total-iterations` budget before completion.")
|
|
119
|
+
if recommendation:
|
|
120
|
+
lines.append(f"- recommendation: {recommendation}")
|
|
121
|
+
resume_line = _resume_summary_line(result)
|
|
122
|
+
if resume_line:
|
|
123
|
+
lines.append(f"- resume: {resume_line}")
|
|
124
|
+
if next_command:
|
|
125
|
+
lines.append(f"- next_command: `{next_command}`")
|
|
126
|
+
elif mission_state_path:
|
|
127
|
+
lines.append(f"- next_command: `deeploop status --mission-state {mission_state_path}`")
|
|
128
|
+
return lines
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def _run_project(args: argparse.Namespace) -> int:
|
|
132
|
+
if not args.until_complete:
|
|
133
|
+
print(
|
|
134
|
+
"error: `deeploop run` requires `--until-complete`; use `deeploop init` plus "
|
|
135
|
+
"`deeploop start`/`deeploop resume` for manual step-by-step control.",
|
|
136
|
+
flush=True,
|
|
137
|
+
)
|
|
138
|
+
return 2
|
|
139
|
+
result = run_project_until_complete(
|
|
140
|
+
Path(args.project_root),
|
|
141
|
+
mission_id=getattr(args, "mission_id", None),
|
|
142
|
+
force=getattr(args, "force", False),
|
|
143
|
+
chunk_iterations=getattr(args, "chunk_iterations", 8),
|
|
144
|
+
max_total_iterations=getattr(args, "max_total_iterations", 256),
|
|
145
|
+
)
|
|
146
|
+
if result["status"] != "completed":
|
|
147
|
+
print("\n".join(_noncompleted_summary_lines(result)), file=sys.stderr, flush=True)
|
|
148
|
+
print(json.dumps(_jsonify(result), indent=2))
|
|
149
|
+
return 0 if result["status"] == "completed" else 1
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def main() -> int:
|
|
153
|
+
parser = argparse.ArgumentParser(
|
|
154
|
+
description=(
|
|
155
|
+
"Run a plain researcher project folder through DeepLoop until completion or a true operator boundary. "
|
|
156
|
+
"This command handles init + bounded start/resume loops for you."
|
|
157
|
+
),
|
|
158
|
+
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
|
159
|
+
)
|
|
160
|
+
_add_run_args(parser)
|
|
161
|
+
args = parser.parse_args()
|
|
162
|
+
return _run_project(args)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
__all__ = ["main", "_add_run_args", "_run_project"]
|
|
@@ -7,7 +7,7 @@ from typing import Any, Mapping
|
|
|
7
7
|
def management_commands(mission_state_path: Path) -> dict[str, str]:
|
|
8
8
|
mission_state_arg = str(mission_state_path)
|
|
9
9
|
return {
|
|
10
|
-
name: f"
|
|
10
|
+
name: f"deeploop {name} --mission-state {mission_state_arg}"
|
|
11
11
|
for name in ("status", "logs", "decisions", "inbox", "resume", "retry", "reroute", "triage", "stop")
|
|
12
12
|
}
|
|
13
13
|
|
|
@@ -130,8 +130,8 @@ def operator_console_snapshot(
|
|
|
130
130
|
|
|
131
131
|
headline = "STOPPED — DeepLoop is not currently running."
|
|
132
132
|
summary = "No operator-facing mission summary is available yet."
|
|
133
|
-
recommendation = "Run status
|
|
134
|
-
continue_summary = "Start or resume
|
|
133
|
+
recommendation = "Run `deeploop status` or `deeploop logs` to inspect the current mission state."
|
|
134
|
+
continue_summary = "Start or resume once the next step is clear."
|
|
135
135
|
gate_class = "none"
|
|
136
136
|
gate_detail = None
|
|
137
137
|
stop_reason = None
|
|
@@ -184,15 +184,15 @@ def operator_console_snapshot(
|
|
|
184
184
|
] or alternatives
|
|
185
185
|
gate_class = str(blocker.get("kind") or blocker.get("gate") or "operator-review")
|
|
186
186
|
gate_detail = str(blocker.get("risk_class") or blocker.get("label") or gate_class)
|
|
187
|
-
headline = "BLOCKED —
|
|
187
|
+
headline = "BLOCKED — review the request, then resume when ready."
|
|
188
188
|
summary = str(current_request.get("summary") or blocker.get("reason") or "DeepLoop opened the operator inbox.")
|
|
189
189
|
recommendation = str(
|
|
190
190
|
recommendation_payload.get("summary")
|
|
191
|
-
or "Review the request, make the smallest safe change, then resume
|
|
191
|
+
or "Review the request, make the smallest safe change, then resume."
|
|
192
192
|
)
|
|
193
193
|
stop_reason = str(blocker.get("reason") or failures.get("completion_reason") or summary)
|
|
194
194
|
requires_action = True
|
|
195
|
-
continue_summary = "
|
|
195
|
+
continue_summary = "Open the inbox, fix or reroute the blocked step, optionally record feedback, then resume."
|
|
196
196
|
next_commands = [
|
|
197
197
|
*(
|
|
198
198
|
[
|
|
@@ -234,7 +234,7 @@ def operator_console_snapshot(
|
|
|
234
234
|
if isinstance(current_response, Mapping):
|
|
235
235
|
action = str(current_response.get("action") or "operator-action")
|
|
236
236
|
continue_summary = (
|
|
237
|
-
f"Operator feedback `{action}` is already recorded. Finish the
|
|
237
|
+
f"Operator feedback `{action}` is already recorded. Finish the change, then resume."
|
|
238
238
|
)
|
|
239
239
|
next_commands = [
|
|
240
240
|
{
|
|
@@ -390,7 +390,7 @@ def operator_console_snapshot(
|
|
|
390
390
|
or failures.get("last_blocker")
|
|
391
391
|
or "The detached mission process exited or has not started yet."
|
|
392
392
|
)
|
|
393
|
-
recommendation = "Inspect status, logs, and decisions,
|
|
393
|
+
recommendation = "Inspect status, logs, and decisions, then resume only after the blocker is understood."
|
|
394
394
|
continue_summary = "Resume only after the blocker is understood and the next step is safe."
|
|
395
395
|
requires_action = mission_status in {"blocked", "failed"}
|
|
396
396
|
next_commands = [
|