cli-agent-runner 0.3.9__tar.gz → 0.3.10__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.
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/.vulture-whitelist.py +1 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/CHANGELOG.md +9 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/PKG-INFO +1 -1
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/_emit/__init__.py +2 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/_emit/serve.py +12 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/_plugin_manifest.py +26 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/_version.py +2 -2
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/agent_runtime.py +12 -2
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/api.py +1 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/builtin_plugins/pi.py +4 -1
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/cli/serve_cmd.py +50 -3
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/config/loader.py +26 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/events.py +1 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/runner.py +15 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/docs/architecture.md +1 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/docs/memory-efficiency.md +65 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/docs/migrations/0.3.md +11 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/docs/plugins.md +1 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/contract/test_public_api_surface.py +1 -0
- cli_agent_runner-0.3.10/tests/e2e/test_e2e_pi_resume.py +344 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_architecture.py +6 -1
- cli_agent_runner-0.3.10/tests/unit/test_apply_resume_env.py +255 -0
- cli_agent_runner-0.3.10/tests/unit/test_config_resume_guard.py +44 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_plugin_manifest.py +29 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/.codecov.yml +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/.github/dependabot.yml +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/.github/workflows/ci.yml +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/.github/workflows/release.yml +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/.gitignore +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/BACKLOG.md +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/CODE_OF_CONDUCT.md +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/CONTRIBUTING.md +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/LICENSE +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/README.md +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/README.zh.md +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/SECURITY.md +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/__init__.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/_docgen.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/_emit/agent.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/_emit/memory.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/_emit/rounds.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/_install.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/_lifecycle.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/_monitor_detectors.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/_monitor_registry.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/_monitor_state.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/_notify.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/_observe.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/_plugin_scan.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/_procwait.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/_redact.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/_registry.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/_resolve.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/_round_outcome.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/_round_support.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/_serve_policy.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/_substrate.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/_throttle.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/api_types.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/builtin_plugins/__init__.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/builtin_plugins/_constants.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/builtin_plugins/claude_rate_limit.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/builtin_plugins/codewhale.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/builtin_plugins/gemini.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/builtin_plugins/kimi.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/cli/__init__.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/cli/__main__.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/cli/_serve_cgroup.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/cli/_serve_round.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/cli/common.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/cli/doctor_cmd.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/cli/events_cmd.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/cli/init_cmd.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/cli/install_cmd.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/cli/migrate_cmd.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/cli/monitor_cmd.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/cli/peek_cmd.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/cli/round_cmd.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/cli/service_cmd.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/cli/upgrade_cmd.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/clock.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/config/__init__.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/config/errors.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/config/models.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/config/parsers.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/config/validators.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/context_store.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/defenses.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/event_log.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/hooks.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/host_health.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/http_progress.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/lifecycle.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/metrics.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/migrations.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/monitor.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/phase_select.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/presets/__init__.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/presets/aider.toml +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/presets/claude.toml +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/presets/codewhale.toml +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/presets/gemini.toml +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/presets/kimi.toml +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/presets/pi.toml +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/prompt_loader.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/remote_relay.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/round_log.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/round_view.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/scaffold.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/schedule.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/service_unit.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/startup_check.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/agent_runner/vcs_state.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/build.sh +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/deploy/Dockerfile +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/deploy/docker-compose.yml +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/docs/README.md +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/docs/commands.md +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/docs/configuration.md +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/docs/events.md +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/docs/long-running-agents.md +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/docs/migrations/0.2.md +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/docs/quickstart.md +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/docs/recipes/aider.md +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/docs/recipes/codewhale.md +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/docs/recipes/container-pi.md +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/docs/recipes/deploy-all-in-one.md +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/docs/recipes/kimi.md +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/docs/recipes/pi.md +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/docs/runbook.md +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/docs/thesis.md +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/pyproject.toml +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/__init__.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/_clock.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/_test_helpers.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/conftest.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/contract/__init__.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/e2e/__init__.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/e2e/conftest.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/e2e/test_e2e_graceful_stop.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/e2e/test_e2e_install_systemd.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/e2e/test_e2e_monitor_remote.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/e2e/test_e2e_round_lifecycle.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/fixtures/cli-real-output/claude-2.1.143-assistant-tool-use.jsonl +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/fixtures/cli-real-output/claude-2.1.143-result-event.jsonl +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/fixtures/cli-real-output/gemini-0.42.0-result-event.jsonl +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/generate_vulture_whitelist.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/integration/__init__.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/integration/test_auto_stop_e2e.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/integration/test_bounded_run.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/integration/test_cooperative_grace_property.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/integration/test_cooperative_stop_signal.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/integration/test_fresh_eyes_signal.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/integration/test_grace_kill_emission.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/integration/test_install_dry_run.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/integration/test_monitor_seeded.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/integration/test_plugin_real_flow.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/integration/test_prompt_delivery_stdin.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/integration/test_reap_property.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/integration/test_run_one_round_with_fake_agent.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/integration/test_scaffold_presets.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/integration/test_serve_loop.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/integration/test_spawn_round_mem_floor.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/integration/test_spawn_round_wedged.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/integration/test_substrate_fingerprint.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/integration/test_transient_error_backoff.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/__init__.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/_docs.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/_event_scan.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_atomic_write_enforced.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_authored_facts_declared.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_auto_stop_policy_ssot.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_bdd_test_conventions.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_brake_defaults_off.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_catalogs.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_classification_ssot.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_config_error_consistency.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_config_value_set_ssot.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_container_stop_bound.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_dataclass_fields_have_producers.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_doc_builtin_plugins.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_doc_claims_match_ssot.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_doc_cli_claims.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_doc_operator_surface.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_doc_test_pointers_exist.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_doc_transient_error_claims.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_doc_usage_event_fields.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_docs_generated.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_docs_index_complete.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_entry_points_resolve.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_event_int_coercion.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_event_kind_registry.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_event_kinds_ssot.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_events_doc_contract.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_gen_blocks_name_their_source.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_hard_wall_signal.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_hook_contract_docs.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_import_footprint.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_layer_2_loop_size.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_migrations_registry_ssot.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_module_boundaries.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_module_sizes.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_monitor_self_exclusion.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_no_ai_signatures.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_no_asyncio_select.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_no_direct_inspect_import.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_no_internal_refs.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_no_price_logic.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_no_pytest_skip_on_parse_fail.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_no_raw_time.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_no_vacuous_invariants.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_no_version_refs.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_peek_schema_version.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_phase_select_stateless.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_plugins_config_stable.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_procwait_shield.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_readme_zh_is_pointer.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_repo_constants_patched_in_tests.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_round_alloc_growth.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_round_log_decode_boundary.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_round_num_single_source.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_round_result_stable.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_set_diff_for_auto_tool_classification.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_stash_uses_sha_not_index.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_throttle_stateless_imports.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_timeout_budget_invariant.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_upstream_schema_canary.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/invariants/test_vulture_whitelist_generated.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/linux/__init__.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/linux/test_memory_high_nudge_e2e.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/literate/__init__.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/literate/parser.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/literate/test_parser.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/literate/test_quickstart.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/__init__.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_agent_runtime.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_agent_runtime_container.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_agent_runtime_grace.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_agent_runtime_marker_scan.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_agent_runtime_progress.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_agent_runtime_reap.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_agent_runtime_signal_name.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_api_assemble_prompt.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_api_events_stream.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_api_install.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_api_observation.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_api_read_round_num.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_api_resolve_phase.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_api_service.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_api_types.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_apply_reap_grace_env.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_auto_stop_gating.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_catalogs.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_cgroup_probe.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_claude_error_detector.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_claude_foreign_schema.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_cli.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_cli_common.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_cli_init_install.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_cli_main_boundary.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_cli_monitor_http.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_cli_service_peek_monitor.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_cli_upgrade.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_codewhale_code_precedence.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_codewhale_plugin.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_coerce_int_poison.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_config.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_config_fresh_eyes.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_config_max_rounds.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_config_nested_strictness.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_config_prompt_delivery.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_config_schedule.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_config_stop_file.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_config_strictness.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_config_substrate_fingerprint_paths.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_config_transient_error_action.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_context_store.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_control_char_config.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_cooperative_signal_env.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_defenses.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_detect_hung_latch.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_detector_isolation.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_docgen.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_doctor_cmd.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_effective_throttle_view.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_emit_config_migrated.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_emit_schedule.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_emit_schedule_phase_skipped.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_event_log.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_events.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_events_cmd.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_events_cmd_rollover.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_events_cmd_tail.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_events_jsonl_decode.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_example_plugin.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_exec_prefix.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_exit_cause.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_exit_classifier.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_fresh_eyes_trigger.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_gemini_plugin.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_git_timeout.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_hook_redact_order.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_hooks.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_host_health.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_http_progress.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_http_progress_epoch.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_init_entry_points.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_interruptible_sleep_should_stop.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_kill_pgroup_shielding.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_kimi_plugin.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_lifecycle.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_loader_split.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_metrics.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_metrics_cgroup_usage.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_metrics_swap.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_migrate_cmd.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_migrations.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_monitor_assembly.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_monitor_cmd_severity.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_monitor_dedup_identity.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_monitor_dedup_rearm.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_monitor_detect_anomaly_repetitive.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_monitor_detect_rate_limit.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_monitor_detect_supervisor_stale.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_monitor_detectors.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_monitor_event_tail.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_monitor_loop.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_monitor_on_alert.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_monitor_remote.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_monitor_round_deferred_stale.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_monitor_schedule_pause.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_network_blip_signal_guard.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_notify.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_open_round_log.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_orphan_chain_single_pass.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_outer_round_ceiling.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_peek_argparse.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_peek_project_isolation.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_peek_schedule.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_peek_select.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_phase_agent_launch.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_phase_profiles.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_phase_select.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_pi_plugin.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_plugin_constants.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_plugin_scan_parity.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_plugins_config_fields.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_presets.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_procwait.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_prompt_loader.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_read_json_hardening.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_redact.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_resolve.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_resolve_dirty_tree.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_round_cmd.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_round_cmd_sigterm.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_round_log_helpers.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_round_outcome.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_round_outcome_agent_axis.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_round_view.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_runner.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_runner_sidecar_ordering.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_runner_throttle.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_scaffold.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_schedule.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_serve_cmd_bounded.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_serve_config_broken.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_serve_crash_loop.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_serve_mem_gate.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_serve_phase_schedule.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_serve_policy.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_serve_round.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_serve_round_cgroup_spine.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_serve_round_log.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_serve_round_oom_killed.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_serve_round_terminate.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_serve_round_wait_exit.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_serve_schedule_gate.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_serve_sentinel.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_serve_wakeup.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_service_mode.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_service_unit.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_startup_battery_exit.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_startup_check.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_substrate.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_supervisor_stale_self_blind.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_terminate_round_wait_exit.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_throttle_back_off_ladder.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_throttle_epoch_bound.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_throttle_plugin_classification.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_upgrade_migrate.py +0 -0
- {cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/unit/test_vcs_state.py +0 -0
|
@@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.3.10] - 2026-09-17
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- Cross-round resume for `pi`: `PluginManifest.resume_flag` (pi = `--session-id`) lets a preset declare an idempotent session flag; `serve` mints one session id per phase and publishes it via `AGENT_RUNNER_RESUME_FLAG`/`AGENT_RUNNER_RESUME_SESSION_ID`, and the round child appends `[flag, id]` to its command. claude/gemini/codewhale/kimi are untouched (`resume_flag` stays `None`) — later release.
|
|
12
|
+
- A new `session_resumed` event records when a round reuses a prior session id.
|
|
13
|
+
- Boot guard: a preset whose static command already contains its `resume_flag` token now fails config load (agent-runner injects it per round; remove the static copy).
|
|
14
|
+
|
|
15
|
+
No config migration — `resume_flag` is a manifest field, not a TOML key. `peek --json` schema stays `2.6`.
|
|
16
|
+
|
|
8
17
|
## [0.3.9] - 2026-09-17
|
|
9
18
|
|
|
10
19
|
### Changed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: cli-agent-runner
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.10
|
|
4
4
|
Summary: Restart-on-exit supervisor for autonomous CLI agents
|
|
5
5
|
Project-URL: Homepage, https://github.com/wan9yu/cli-agent-runner
|
|
6
6
|
Project-URL: Documentation, https://github.com/wan9yu/cli-agent-runner#readme
|
|
@@ -65,6 +65,7 @@ from agent_runner._emit.serve import ( # noqa: F401 — public re-export
|
|
|
65
65
|
emit_schedule_paused,
|
|
66
66
|
emit_schedule_phase_skipped,
|
|
67
67
|
emit_schedule_resumed,
|
|
68
|
+
emit_session_resumed,
|
|
68
69
|
emit_stalled_no_progress,
|
|
69
70
|
emit_stop_file_detected,
|
|
70
71
|
)
|
|
@@ -104,6 +105,7 @@ __all__ = [
|
|
|
104
105
|
"emit_schedule_paused",
|
|
105
106
|
"emit_schedule_phase_skipped",
|
|
106
107
|
"emit_schedule_resumed",
|
|
108
|
+
"emit_session_resumed",
|
|
107
109
|
"emit_stale_index_lock_cleared",
|
|
108
110
|
"emit_stalled_no_progress",
|
|
109
111
|
"emit_stop_file_detected",
|
|
@@ -191,3 +191,15 @@ def emit_schedule_resumed(log_dir: Path, *, paused_for_s: int) -> None:
|
|
|
191
191
|
from agent_runner.events import SCHEDULE_RESUMED, emit
|
|
192
192
|
|
|
193
193
|
emit(log_dir, SCHEDULE_RESUMED, paused_for_s=paused_for_s)
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def emit_session_resumed(log_dir: Path, *, session_id: str, phase: str = "") -> None:
|
|
197
|
+
"""Emit session_resumed when serve resumes an existing agent session on a
|
|
198
|
+
non-first round of an epoch (the runtime property peek cannot show). ``phase``
|
|
199
|
+
is omitted when empty so the base (no-override) phase stays a clean payload."""
|
|
200
|
+
from agent_runner.events import SESSION_RESUMED, emit
|
|
201
|
+
|
|
202
|
+
fields = {"session_id": session_id}
|
|
203
|
+
if phase:
|
|
204
|
+
fields["phase"] = phase
|
|
205
|
+
emit(log_dir, SESSION_RESUMED, **fields)
|
|
@@ -43,6 +43,13 @@ class PluginManifest:
|
|
|
43
43
|
SIGTERM-first at the reap site (today's behavior), never "skip the first
|
|
44
44
|
signal"."""
|
|
45
45
|
|
|
46
|
+
resume_flag: str | None = None
|
|
47
|
+
"""The flag that carries a supervisor-chosen session id on EVERY round for a
|
|
48
|
+
CLI whose session flag is IDEMPOTENT (create-or-resume). pi = "--session-id".
|
|
49
|
+
``None`` = no resume (today's cold start). Resolved ONLY by
|
|
50
|
+
``resolve_resume_flag``; ``__post_init__`` rejects an empty string. Source-
|
|
51
|
+
verified per preset (pi's --session-id is idempotent), NEVER assumed."""
|
|
52
|
+
|
|
46
53
|
def __post_init__(self) -> None:
|
|
47
54
|
# Errors-unlikely-by-construction: an unknown signal name (or a
|
|
48
55
|
# freeze/zero-grace one like SIGSTOP/SIGKILL) is unrepresentable -- it
|
|
@@ -52,6 +59,10 @@ class PluginManifest:
|
|
|
52
59
|
"cooperative_stop must be one of {None, 'SIGTERM', 'SIGINT'}, "
|
|
53
60
|
f"got {self.cooperative_stop!r}"
|
|
54
61
|
)
|
|
62
|
+
if self.resume_flag is not None and not self.resume_flag:
|
|
63
|
+
raise ValueError(
|
|
64
|
+
f"resume_flag must be None or a non-empty flag string, got {self.resume_flag!r}"
|
|
65
|
+
)
|
|
55
66
|
|
|
56
67
|
|
|
57
68
|
_LOADED_MANIFESTS: list[PluginManifest] = []
|
|
@@ -102,6 +113,21 @@ def resolve_cooperative_signal(agent_binary: str | None) -> signal.Signals | Non
|
|
|
102
113
|
return _COOPERATIVE_SIGNALS.get(_cooperative_stop_for_name(agent_binary))
|
|
103
114
|
|
|
104
115
|
|
|
116
|
+
def resolve_resume_flag(agent_binary: str | None) -> str | None:
|
|
117
|
+
"""The resume flag the agent named `agent_binary` declares, or None when no
|
|
118
|
+
such manifest is registered (or it declares no resume). THE registry lookup
|
|
119
|
+
for resume -- sibling to resolve_cooperative_signal, the SAME
|
|
120
|
+
``m.name == agent_binary`` join (so it stays correct whenever a preset's
|
|
121
|
+
manifest name is kept equal to its agent binary). serve resolves it once
|
|
122
|
+
per phase and publishes the id via env so the round child never
|
|
123
|
+
re-derives. No signal table: the flag string IS what serve publishes and
|
|
124
|
+
the child appends, so the scan IS the resolve."""
|
|
125
|
+
for m in _LOADED_MANIFESTS:
|
|
126
|
+
if m.name == agent_binary:
|
|
127
|
+
return m.resume_flag
|
|
128
|
+
return None
|
|
129
|
+
|
|
130
|
+
|
|
105
131
|
def cooperative_signal_from_name(name: str | None) -> signal.Signals | None:
|
|
106
132
|
"""Map a published cooperative-stop signal NAME (e.g. from
|
|
107
133
|
AGENT_RUNNER_COOPERATIVE_STOP_SIGNAL) back to a ``signal.Signals`` through
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '0.3.
|
|
22
|
-
__version_tuple__ = version_tuple = (0, 3,
|
|
21
|
+
__version__ = version = '0.3.10'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 3, 10)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -634,6 +634,7 @@ def run(
|
|
|
634
634
|
clock: Clock = SYSTEM_CLOCK,
|
|
635
635
|
reap_grace_s: int = REAP_GRACE_S,
|
|
636
636
|
cooperative_first_signal: signal.Signals = signal.SIGTERM,
|
|
637
|
+
resume_args: tuple[str, ...] = (),
|
|
637
638
|
) -> RunResult:
|
|
638
639
|
"""Spawn the agent subprocess and wait for exit or timeout.
|
|
639
640
|
|
|
@@ -653,6 +654,14 @@ def run(
|
|
|
653
654
|
cooperative_stop / standalone `agent-runner round`), so every existing caller
|
|
654
655
|
is unchanged.
|
|
655
656
|
|
|
657
|
+
resume_args: ``[flag, session_id]`` appended after ``command`` and before
|
|
658
|
+
the prompt args, for a resume-capable agent picking its session back up
|
|
659
|
+
across rounds. The id is minted once by the caller's own env-published
|
|
660
|
+
single-source (``runner._resolve_resume_args``) and copied verbatim here --
|
|
661
|
+
this module never mints or derives one (no ``os.environ`` read for the
|
|
662
|
+
session id; see the module docstring). Defaults to ``()``, so every
|
|
663
|
+
existing caller's argv is byte-identical to before.
|
|
664
|
+
|
|
656
665
|
work_dir: the agent child's working directory; callers pass the
|
|
657
666
|
already-absolute cfg.runtime.work_dir. CLIs with no --cwd flag of their
|
|
658
667
|
own (e.g. pi) depend on this.
|
|
@@ -760,10 +769,11 @@ def run(
|
|
|
760
769
|
# template for stdin mode, but run() must be safe even if called
|
|
761
770
|
# directly with a mismatched template. In stdin mode, never substitute
|
|
762
771
|
# {prompt} into argv — build it verbatim so the prompt cannot reach argv.
|
|
772
|
+
resumed_command = list(spawn_command) + list(resume_args)
|
|
763
773
|
argv = (
|
|
764
|
-
list(
|
|
774
|
+
list(resumed_command) + list(prompt_arg_template)
|
|
765
775
|
if stdin_mode
|
|
766
|
-
else _build_argv(
|
|
776
|
+
else _build_argv(resumed_command, prompt_arg_template, prompt)
|
|
767
777
|
)
|
|
768
778
|
# PWD pinned last — it mirrors cwd= (a correctness pin, not a knob), so
|
|
769
779
|
# an [agent.env] PWD cannot silently diverge from where the child runs.
|
|
@@ -62,6 +62,7 @@ from agent_runner._emit import ( # noqa: E402,F401 — intentional bottom re-ex
|
|
|
62
62
|
emit_schedule_paused,
|
|
63
63
|
emit_schedule_phase_skipped,
|
|
64
64
|
emit_schedule_resumed,
|
|
65
|
+
emit_session_resumed,
|
|
65
66
|
emit_stale_index_lock_cleared,
|
|
66
67
|
emit_stalled_no_progress,
|
|
67
68
|
emit_stop_file_detected,
|
|
@@ -281,5 +281,8 @@ def _is_auth_error(text: str | None) -> bool:
|
|
|
281
281
|
|
|
282
282
|
|
|
283
283
|
PLUGIN = PluginManifest(
|
|
284
|
-
name="pi",
|
|
284
|
+
name="pi",
|
|
285
|
+
post_round_hooks=(PiErrorDetector(),),
|
|
286
|
+
cooperative_stop="SIGTERM",
|
|
287
|
+
resume_flag="--session-id",
|
|
285
288
|
)
|
|
@@ -43,6 +43,7 @@ from agent_runner.api import (
|
|
|
43
43
|
emit_schedule_paused,
|
|
44
44
|
emit_schedule_phase_skipped,
|
|
45
45
|
emit_schedule_resumed,
|
|
46
|
+
emit_session_resumed,
|
|
46
47
|
emit_stop_file_detected,
|
|
47
48
|
outer_round_ceiling_s,
|
|
48
49
|
)
|
|
@@ -558,9 +559,8 @@ def _is_fresh_eyes_round(*, round_num: int, every_n: int | None) -> bool:
|
|
|
558
559
|
return round_num % every_n == 0
|
|
559
560
|
|
|
560
561
|
|
|
561
|
-
def _apply_fresh_eyes(cfg, log_dir, round_num: int, round_env: dict) -> None:
|
|
562
|
+
def _apply_fresh_eyes(cfg, log_dir, round_num: int, round_env: dict, fresh_eyes: bool) -> None:
|
|
562
563
|
"""Set the round's fresh-eyes env flag and emit the trigger event when due."""
|
|
563
|
-
fresh_eyes = _is_fresh_eyes_round(round_num=round_num, every_n=cfg.runtime.fresh_eyes_every_n)
|
|
564
564
|
round_env["AGENT_RUNNER_FRESH_EYES"] = "1" if fresh_eyes else "0"
|
|
565
565
|
if fresh_eyes:
|
|
566
566
|
emit_fresh_eyes_round_triggered(
|
|
@@ -659,6 +659,45 @@ def _apply_cooperative_signal_env(
|
|
|
659
659
|
round_env["AGENT_RUNNER_COOPERATIVE_STOP_SIGNAL"] = name
|
|
660
660
|
|
|
661
661
|
|
|
662
|
+
def _apply_resume_env(
|
|
663
|
+
cfg, round_env: dict, phase_arg: str | None, is_fresh_eyes: bool, session_ids: dict, log_dir
|
|
664
|
+
) -> None:
|
|
665
|
+
"""Publish this round's cross-round-resume flag + session id via
|
|
666
|
+
AGENT_RUNNER_RESUME_FLAG / AGENT_RUNNER_RESUME_SESSION_ID -- the 4th
|
|
667
|
+
serve->child env single-source (siblings _apply_reap_grace_env /
|
|
668
|
+
_apply_cooperative_signal_env). UNLIKE those boot-invariant siblings the id
|
|
669
|
+
is MUTABLE per-phase state: `session_ids` (keyed by PHASE, not binary --
|
|
670
|
+
per-role continuity) carries it across rounds; a first-use OR fresh-eyes
|
|
671
|
+
round mints a new uuid. A non-resume phase (resolve_resume_flag is None)
|
|
672
|
+
POPS both keys so a prior resume-capable phase's id never leaks onto this
|
|
673
|
+
round's child argv. Emits session_resumed only when RESUMING (id reused)."""
|
|
674
|
+
import uuid
|
|
675
|
+
|
|
676
|
+
from agent_runner._plugin_manifest import resolve_resume_flag
|
|
677
|
+
|
|
678
|
+
# Resume needs serve to PIN the child's phase. When phase_arg is None but
|
|
679
|
+
# [phases] exists, serve is non-phase-aware (phase_policy="wait", or
|
|
680
|
+
# --ignore-schedule) and the round child SELF-ROTATES phases by round_num --
|
|
681
|
+
# serve cannot know which agent ran, so publishing the base id would bleed
|
|
682
|
+
# one role's session across all rotated roles. Cold-start (pop) when the
|
|
683
|
+
# phase is ambiguous; resume only with an explicit phase or a single base
|
|
684
|
+
# agent (empty phases.list).
|
|
685
|
+
flag = resolve_resume_flag(cfg.profile_for(phase_arg).agent.binary)
|
|
686
|
+
if flag is None or (phase_arg is None and cfg.phases.list):
|
|
687
|
+
round_env.pop("AGENT_RUNNER_RESUME_FLAG", None)
|
|
688
|
+
round_env.pop("AGENT_RUNNER_RESUME_SESSION_ID", None)
|
|
689
|
+
return
|
|
690
|
+
sid = session_ids.get(phase_arg)
|
|
691
|
+
resuming = sid is not None and not is_fresh_eyes
|
|
692
|
+
if not resuming:
|
|
693
|
+
sid = str(uuid.uuid4())
|
|
694
|
+
session_ids[phase_arg] = sid
|
|
695
|
+
round_env["AGENT_RUNNER_RESUME_FLAG"] = flag
|
|
696
|
+
round_env["AGENT_RUNNER_RESUME_SESSION_ID"] = sid
|
|
697
|
+
if resuming:
|
|
698
|
+
emit_session_resumed(log_dir, session_id=sid, phase=phase_arg or "")
|
|
699
|
+
|
|
700
|
+
|
|
662
701
|
def _capture_substrate(work_dir, cfg, log_dir, round_num, *, when):
|
|
663
702
|
"""Snapshot git-head + paths-hash and emit the round-substrate event for `when`."""
|
|
664
703
|
git_head = compute_git_head(work_dir)
|
|
@@ -742,6 +781,10 @@ def cmd(args) -> int:
|
|
|
742
781
|
_release_serve_lock(serve_lock_fd)
|
|
743
782
|
raise ConfigError(f"phase-window overlap: {detail}; run `agent-runner doctor` for details")
|
|
744
783
|
rounds_completed = 0
|
|
784
|
+
# Cross-round resume: this serve lifetime's minted session id per phase
|
|
785
|
+
# (None key = the base, no-override agent). Mutable, unlike grace_by_phase/
|
|
786
|
+
# cooperative_signal_by_phase above -- see _apply_resume_env.
|
|
787
|
+
session_ids: dict[str | None, str] = {}
|
|
745
788
|
# Three independent consecutive-failure counters, one per breaker: b12
|
|
746
789
|
# crash-loop (unknown short crashes), mem-loop (mem-terminated
|
|
747
790
|
# rounds), no-progress (exit-0, no usage). LOC-neutral
|
|
@@ -801,10 +844,14 @@ def cmd(args) -> int:
|
|
|
801
844
|
if stop["requested"]:
|
|
802
845
|
break # SIGTERM landed during selection/back-off — don't spawn a round
|
|
803
846
|
_capture_substrate(work_dir, cfg, log_dir, round_num, when="before")
|
|
804
|
-
|
|
847
|
+
is_fresh_eyes = _is_fresh_eyes_round(
|
|
848
|
+
round_num=round_num, every_n=cfg.runtime.fresh_eyes_every_n
|
|
849
|
+
)
|
|
850
|
+
_apply_fresh_eyes(cfg, log_dir, round_num, round_env, is_fresh_eyes)
|
|
805
851
|
_apply_round_num_env(round_env, round_num)
|
|
806
852
|
_apply_reap_grace_env(cfg, round_env, phase_arg, grace_by_phase)
|
|
807
853
|
_apply_cooperative_signal_env(cfg, round_env, phase_arg, cooperative_signal_by_phase)
|
|
854
|
+
_apply_resume_env(cfg, round_env, phase_arg, is_fresh_eyes, session_ids, log_dir)
|
|
808
855
|
round_log_path = log_dir / f"round-{round_num}.log"
|
|
809
856
|
round_started = SYSTEM_CLOCK.monotonic()
|
|
810
857
|
round_argv = [
|
|
@@ -32,6 +32,30 @@ from agent_runner.config.validators import (
|
|
|
32
32
|
_CURRENT_SCHEMA_VERSION = 1
|
|
33
33
|
|
|
34
34
|
|
|
35
|
+
def _reject_static_resume_flag(cfg) -> None:
|
|
36
|
+
"""A resume-capable preset must not already carry its resume_flag token in
|
|
37
|
+
the static command/prompt_arg_template -- agent-runner injects [flag, id]
|
|
38
|
+
per round, so a static copy would duplicate it. Boot refusal (ConfigError)
|
|
39
|
+
keeps best-effort-never-error at round time. Runs AFTER
|
|
40
|
+
load_and_register_plugins so resolve_resume_flag can see the manifests
|
|
41
|
+
(it is registry-backed, unlike the boot-time {prompt} guard)."""
|
|
42
|
+
from agent_runner._plugin_manifest import resolve_resume_flag
|
|
43
|
+
|
|
44
|
+
agents = [(None, cfg.agent)] + [
|
|
45
|
+
(name, ov.agent) for name, ov in cfg.phases.overrides.items() if ov.agent is not None
|
|
46
|
+
]
|
|
47
|
+
for phase_name, a in agents:
|
|
48
|
+
flag = resolve_resume_flag(a.binary)
|
|
49
|
+
if flag is None:
|
|
50
|
+
continue
|
|
51
|
+
if flag in a.command or flag in a.prompt_arg_template:
|
|
52
|
+
where = "[agent]" if phase_name is None else f"[phases.{phase_name}.agent]"
|
|
53
|
+
raise ConfigError(
|
|
54
|
+
f"{where} command already contains {flag!r}: agent-runner injects it "
|
|
55
|
+
"per round for cross-round resume; remove it from the static command"
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
|
|
35
59
|
def _check_schema_version(raw: dict) -> None:
|
|
36
60
|
"""Boot gate: a config's ``schema_version`` decouples the on-disk config
|
|
37
61
|
shape from the installed package version, so a config can be migrated
|
|
@@ -133,4 +157,6 @@ def load_config(toml_path: Path) -> Config:
|
|
|
133
157
|
if plugins.disable:
|
|
134
158
|
apply_plugin_disable(plugins.disable)
|
|
135
159
|
|
|
160
|
+
_reject_static_resume_flag(cfg)
|
|
161
|
+
|
|
136
162
|
return cfg
|
|
@@ -84,6 +84,7 @@ SELF_TERMINATED = "agent_self_terminated"
|
|
|
84
84
|
SERVICE_UPGRADE_ROLLBACK_FAILED = "service_upgrade_rollback_failed"
|
|
85
85
|
SERVICE_UPGRADE_ROLLED_BACK = "service_upgrade_rolled_back"
|
|
86
86
|
SERVICE_UPGRADED = "service_upgraded"
|
|
87
|
+
SESSION_RESUMED = "session_resumed"
|
|
87
88
|
SMOKE_CHECK_FAILED = "smoke_check_failed"
|
|
88
89
|
STALE_INDEX_LOCK_CLEARED = "stale_index_lock_cleared"
|
|
89
90
|
STALLED_NO_PROGRESS = "stalled_no_progress"
|
|
@@ -220,6 +220,20 @@ def _resolve_cooperative_signal() -> signal.Signals:
|
|
|
220
220
|
return resolved if resolved is not None else signal.SIGTERM
|
|
221
221
|
|
|
222
222
|
|
|
223
|
+
def _resolve_resume_args() -> list[str]:
|
|
224
|
+
"""The ``[flag, session_id]`` the round child appends for cross-round
|
|
225
|
+
resume, or ``[]`` when no serve parent published them (systemd / standalone
|
|
226
|
+
``round`` -> cold start by construction). Pure consumption -- the id is
|
|
227
|
+
minted once serve-side and copied verbatim; the child NEVER derives it.
|
|
228
|
+
Sibling of ``_resolve_reap_grace_s`` / ``_resolve_cooperative_signal``: the
|
|
229
|
+
same serve->child env single-source, both-vars-or-neither."""
|
|
230
|
+
flag = os.environ.get("AGENT_RUNNER_RESUME_FLAG")
|
|
231
|
+
session_id = os.environ.get("AGENT_RUNNER_RESUME_SESSION_ID")
|
|
232
|
+
if flag and session_id:
|
|
233
|
+
return [flag, session_id]
|
|
234
|
+
return []
|
|
235
|
+
|
|
236
|
+
|
|
223
237
|
def _previous_block(prev: context_store.Status | None, dirty_last: bool) -> dict[str, Any] | None:
|
|
224
238
|
if prev is None:
|
|
225
239
|
return None
|
|
@@ -507,6 +521,7 @@ def _run_one_round_inner(cfg: Config, *, phase_override: str | None = None) -> R
|
|
|
507
521
|
on_container_orphan_risk=_container_orphan_risk_emit,
|
|
508
522
|
reap_grace_s=_resolve_reap_grace_s(),
|
|
509
523
|
cooperative_first_signal=_resolve_cooperative_signal(),
|
|
524
|
+
resume_args=_resolve_resume_args(),
|
|
510
525
|
)
|
|
511
526
|
events.emit(
|
|
512
527
|
log_dir,
|
|
@@ -248,6 +248,7 @@ The result is recorded as `RoundResult.dirty_outcome: DirtyOutcome | None`, whic
|
|
|
248
248
|
- `service_upgrade_rollback_failed`
|
|
249
249
|
- `service_upgrade_rolled_back`
|
|
250
250
|
- `service_upgraded`
|
|
251
|
+
- `session_resumed`
|
|
251
252
|
- `smoke_check_failed`
|
|
252
253
|
- `stale_index_lock_cleared`
|
|
253
254
|
- `stalled_no_progress`
|
|
@@ -652,6 +652,71 @@ since 0.2.17. No constrained-host-specific claim this release — the
|
|
|
652
652
|
subtraction is host-independent code removal, not a runtime-behavior change
|
|
653
653
|
under pressure.
|
|
654
654
|
|
|
655
|
+
## 0.3.9 → 0.3.10
|
|
656
|
+
|
|
657
|
+
Cross-round resume for `pi`: `PluginManifest.resume_flag` (a new dataclass
|
|
658
|
+
field, `str | None`, default `None`), `resolve_resume_flag`, a per-phase
|
|
659
|
+
session-id mint + env publish (`AGENT_RUNNER_RESUME_FLAG`/
|
|
660
|
+
`AGENT_RUNNER_RESUME_SESSION_ID`) in `serve_cmd`, the round child appending
|
|
661
|
+
`[flag, id]`, a `session_resumed` event, and a config boot guard. Same macOS
|
|
662
|
+
harness (§ methodology above), comparing **v0.3.9** = `095c5f1` (measured in a
|
|
663
|
+
throwaway worktree) against **0.3.10**, the tip of this branch.
|
|
664
|
+
|
|
665
|
+
### 1. Import/startup RSS
|
|
666
|
+
|
|
667
|
+
| | v0.3.9 | 0.3.10 | Δ |
|
|
668
|
+
|---|---|---|---|
|
|
669
|
+
| RSS (avg of 5 cold runs) | 23.42 MB | 23.39 MB | −0.03 MB (flat, within noise) |
|
|
670
|
+
| RSS range | 23.39–23.45 MB | 23.34–23.42 MB | |
|
|
671
|
+
| `sys.modules` count | 211 | 211 | +0 |
|
|
672
|
+
|
|
673
|
+
Flat, as expected: `uuid` (the only new stdlib name resume touches) is
|
|
674
|
+
imported inside `_apply_resume_env`, not at module level, so it never joins
|
|
675
|
+
the cold-startup graph — confirmed directly (`"uuid" in sys.modules` is
|
|
676
|
+
`False` after `import agent_runner.cli`), not just inferred from a flat RSS
|
|
677
|
+
number. A direct `sys.modules` set diff (not just the count) confirms the
|
|
678
|
+
`agent_runner.*` module set `import agent_runner.cli` loads is byte-for-byte
|
|
679
|
+
identical, 211 modules, before and after — the same check this page has run
|
|
680
|
+
at every release since 0.3.9's own close-out.
|
|
681
|
+
|
|
682
|
+
### 2. Base dependencies
|
|
683
|
+
|
|
684
|
+
Unchanged: `psutil>=5.9` is still the only runtime dependency
|
|
685
|
+
(`pip show cli-agent-runner` → `Requires: psutil`). Resume introduces no new
|
|
686
|
+
dependency and no new extra.
|
|
687
|
+
|
|
688
|
+
### 3. Module count, source LOC, largest module
|
|
689
|
+
|
|
690
|
+
Tracked source only (`git ls-tree`, same convention as the rows above).
|
|
691
|
+
|
|
692
|
+
| | v0.3.9 | 0.3.10 | Δ |
|
|
693
|
+
|---|---|---|---|
|
|
694
|
+
| `.py` files | 81 | 81 | +0 |
|
|
695
|
+
| total LOC | 20,195 | 20,338 | +143 |
|
|
696
|
+
| largest module | `migrations.py`, 972 | `migrations.py`, 972 | +0 |
|
|
697
|
+
|
|
698
|
+
The `+143` LOC is the new manifest field, its resolver, the boot guard, the
|
|
699
|
+
per-phase env publish/consume, the `session_resumed` event, and their tests
|
|
700
|
+
— no module decomposition this release.
|
|
701
|
+
|
|
702
|
+
### 4. Per-round allocation growth
|
|
703
|
+
|
|
704
|
+
`tests/invariants/test_round_alloc_growth.py` green, unmodified harness.
|
|
705
|
+
`_apply_resume_env` runs once per round (same call site as the other
|
|
706
|
+
per-round `serve_cmd` readers) and, on the no-resume branch every
|
|
707
|
+
non-`pi` preset takes, does two dict `.pop()`s and returns — no new retained
|
|
708
|
+
per-round state. On the resume branch (`pi` only), the session id is minted
|
|
709
|
+
once per phase at `serve` startup (`session_ids` dict, sized by phase count,
|
|
710
|
+
not by round count) and reused verbatim every round after — not re-allocated
|
|
711
|
+
per round.
|
|
712
|
+
|
|
713
|
+
### Constrained-host (honesty)
|
|
714
|
+
|
|
715
|
+
Dev-host-relative (macOS) numbers only, same methodology as every release
|
|
716
|
+
since 0.2.17. No constrained-host-specific claim this release — resume is a
|
|
717
|
+
pi-only session-id mechanism verified so far by an ssh-pi property test, not
|
|
718
|
+
a memory-pressure-path change.
|
|
719
|
+
|
|
655
720
|
## Enforcement
|
|
656
721
|
|
|
657
722
|
Four invariant tests keep these numbers from drifting silently:
|
|
@@ -127,3 +127,14 @@ rather than partially trusted. The exact errors:
|
|
|
127
127
|
|
|
128
128
|
Any of these means the same fix: run `agent-runner migrate` (or, for the
|
|
129
129
|
newer-than-supported case, upgrade the `agent-runner` package instead).
|
|
130
|
+
|
|
131
|
+
## Upgrading to 0.3.10 — no config migration
|
|
132
|
+
|
|
133
|
+
0.3.10 adds cross-round resume (`PluginManifest.resume_flag`, pi's
|
|
134
|
+
`--session-id`). It is additive and inert for every preset that doesn't
|
|
135
|
+
declare a `resume_flag` — nothing to run, nothing to rewrite. If your config
|
|
136
|
+
already passes `--session-id` (or another preset's resume flag) as a static
|
|
137
|
+
argument in `[agent] command`/`prompt_arg_template` (or a `[phases.<name>]`
|
|
138
|
+
override), remove it: agent-runner now injects `[flag, session id]` itself on
|
|
139
|
+
every round for a resume-capable preset, and a static copy of the same flag
|
|
140
|
+
fails config load at boot.
|
|
@@ -47,6 +47,7 @@ empty:
|
|
|
47
47
|
| `name` | `str` | The plugin's own identity — `[plugins] disable` keys on this, not on any individual hook's own `.name`. |
|
|
48
48
|
| `post_round_hooks` | `tuple[PostRoundHook, ...]` | Runs after each agent round. |
|
|
49
49
|
| `cooperative_stop` | `Literal["SIGTERM", "SIGINT"] \| None` | The signal this preset's agent CLI catches to drain/wrap up when a round is stopped (`None` = no cooperative drain — the hard SIGTERM-first path). Reported under `peek --json`'s `plugins.cooperative_stop` (§ below). |
|
|
50
|
+
| `resume_flag` | `str \| None` | The idempotent session flag `serve` injects on every round of this preset for cross-round resume (pi = `--session-id`); `serve` mints one session id per phase and the round child appends `[flag, id]` to its command. `None` = no resume (cold start every round, today's behavior for every other preset). |
|
|
50
51
|
|
|
51
52
|
A plugin that provides more than one capability just fills in more than one
|
|
52
53
|
field on the same manifest — there is nothing to register per-capability.
|
{cli_agent_runner-0.3.9 → cli_agent_runner-0.3.10}/tests/contract/test_public_api_surface.py
RENAMED
|
@@ -217,6 +217,7 @@ EXPECTED_API_SURFACE = {
|
|
|
217
217
|
"emit_schedule_paused",
|
|
218
218
|
"emit_schedule_phase_skipped",
|
|
219
219
|
"emit_schedule_resumed",
|
|
220
|
+
"emit_session_resumed",
|
|
220
221
|
"emit_stale_index_lock_cleared",
|
|
221
222
|
# "emit_stalled_no_progress" added 0.2.16 Task 6: exit-0 no-progress breaker
|
|
222
223
|
# (pi-class CLIs exit 0 on a provider failure that never reaches the model).
|