cli-agent-runner 0.2.15__tar.gz → 0.2.17__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.2.15 → cli_agent_runner-0.2.17}/.vulture-whitelist.py +11 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/CHANGELOG.md +31 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/PKG-INFO +2 -2
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/README.md +1 -1
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/_emit.py +153 -3
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/_serve_policy.py +88 -7
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/_throttle.py +234 -40
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/_version.py +2 -2
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/api.py +26 -3
- cli_agent_runner-0.2.17/agent_runner/cli/_serve_round.py +534 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/cli/serve_cmd.py +87 -300
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/config/models.py +15 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/config/parsers.py +17 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/config/validators.py +12 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/defenses.py +23 -2
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/events.py +5 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/host_health.py +14 -9
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/metrics.py +113 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/monitor.py +62 -16
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/service_unit.py +7 -3
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/docs/architecture.md +15 -7
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/docs/commands.md +1 -1
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/docs/configuration.md +5 -1
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/docs/migrations/0.2.md +76 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/docs/runbook.md +54 -22
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/contract/test_public_api_surface.py +8 -0
- cli_agent_runner-0.2.17/tests/integration/test_spawn_round_mem_floor.py +548 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/integration/test_spawn_round_wedged.py +5 -4
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_architecture.py +106 -31
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_event_kinds_ssot.py +9 -1
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_module_boundaries.py +1 -1
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_timeout_budget_invariant.py +1 -1
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_api_service.py +3 -3
- cli_agent_runner-0.2.17/tests/unit/test_cgroup_probe.py +233 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_config.py +75 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_defenses.py +2 -2
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_host_health.py +13 -0
- cli_agent_runner-0.2.17/tests/unit/test_monitor_dedup_rearm.py +104 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_monitor_remote.py +37 -0
- cli_agent_runner-0.2.17/tests/unit/test_round_outcome.py +319 -0
- cli_agent_runner-0.2.17/tests/unit/test_serve_crash_loop.py +640 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_serve_mem_gate.py +25 -1
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_serve_policy.py +67 -0
- cli_agent_runner-0.2.17/tests/unit/test_serve_round.py +34 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_service_unit.py +27 -2
- cli_agent_runner-0.2.15/tests/integration/test_spawn_round_mem_floor.py +0 -224
- cli_agent_runner-0.2.15/tests/unit/test_monitor_dedup_rearm.py +0 -42
- cli_agent_runner-0.2.15/tests/unit/test_serve_crash_loop.py +0 -226
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/.codecov.yml +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/.github/workflows/ci.yml +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/.github/workflows/release.yml +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/.gitignore +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/BACKLOG.md +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/CODE_OF_CONDUCT.md +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/CONTRIBUTING.md +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/LICENSE +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/README.zh.md +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/SECURITY.md +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/__init__.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/_docgen.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/_monitor_detectors.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/_monitor_registry.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/_monitor_state.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/_redact.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/_registry.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/_resolve.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/_round_support.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/_substrate.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/agent_runtime.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/api_types.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/builtin_plugins/__init__.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/builtin_plugins/_constants.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/builtin_plugins/claude_rate_limit.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/builtin_plugins/codewhale.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/builtin_plugins/default_dirty_handler.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/builtin_plugins/gemini.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/builtin_plugins/kimi.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/builtin_plugins/pi.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/cli/__init__.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/cli/__main__.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/cli/common.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/cli/events_cmd.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/cli/init_cmd.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/cli/install_cmd.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/cli/migrate_cmd.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/cli/monitor_cmd.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/cli/peek_cmd.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/cli/round_cmd.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/cli/service_cmd.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/cli/upgrade_cmd.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/clock.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/config/__init__.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/config/errors.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/config/loader.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/context_store.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/hooks.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/http_progress.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/lifecycle.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/migrations.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/phase_select.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/presets/__init__.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/presets/aider.toml +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/presets/claude.toml +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/presets/codewhale.toml +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/presets/gemini.toml +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/presets/kimi.toml +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/presets/pi.toml +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/prompt_loader.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/remote_relay.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/round_log.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/round_view.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/runner.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/scaffold.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/schedule.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/startup_check.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/agent_runner/vcs_state.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/build.sh +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/docs/README.md +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/docs/events.md +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/docs/long-running-agents.md +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/docs/plugins.md +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/docs/quickstart.md +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/docs/recipes/aider.md +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/docs/recipes/codewhale.md +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/docs/recipes/kimi.md +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/docs/recipes/pi.md +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/docs/thesis.md +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/pyproject.toml +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/__init__.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/_clock.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/_test_helpers.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/conftest.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/contract/__init__.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/e2e/__init__.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/e2e/conftest.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/e2e/test_e2e_graceful_stop.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/e2e/test_e2e_install_systemd.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/e2e/test_e2e_monitor_remote.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/e2e/test_e2e_round_lifecycle.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/fixtures/cli-real-output/claude-2.1.143-assistant-tool-use.jsonl +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/fixtures/cli-real-output/claude-2.1.143-result-event.jsonl +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/fixtures/cli-real-output/gemini-0.42.0-result-event.jsonl +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/generate_vulture_whitelist.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/integration/__init__.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/integration/test_auto_stop_e2e.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/integration/test_bounded_run.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/integration/test_context_enricher_namespacing.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/integration/test_dirty_handler_seam.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/integration/test_fresh_eyes_signal.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/integration/test_grace_kill_emission.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/integration/test_install_dry_run.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/integration/test_monitor_seeded.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/integration/test_plugin_detector_loaded.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/integration/test_plugin_owned_paths.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/integration/test_plugin_real_flow.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/integration/test_prompt_delivery_stdin.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/integration/test_run_one_round_with_fake_agent.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/integration/test_scaffold_presets.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/integration/test_serve_loop.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/integration/test_substrate_fingerprint.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/integration/test_transient_error_backoff.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/__init__.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/_docs.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/_event_scan.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_atomic_write_enforced.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_authored_facts_declared.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_auto_stop_policy_ssot.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_catalogs.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_classification_ssot.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_config_error_consistency.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_config_value_set_ssot.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_dataclass_fields_have_producers.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_doc_builtin_plugins.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_doc_claims_match_ssot.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_doc_cli_claims.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_doc_operator_surface.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_doc_test_pointers_exist.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_doc_transient_error_claims.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_doc_usage_event_fields.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_docs_generated.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_docs_index_complete.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_entry_points_resolve.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_event_int_coercion.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_event_kind_registry.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_events_doc_contract.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_gen_blocks_name_their_source.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_hook_contract_docs.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_layer_2_loop_size.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_migrations_registry_ssot.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_module_sizes.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_monitor_self_exclusion.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_no_ai_signatures.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_no_internal_refs.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_no_pytest_skip_on_parse_fail.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_no_raw_time.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_no_vacuous_invariants.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_peek_schema_version.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_phase_select_stateless.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_plugins_config_stable.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_readme_zh_is_pointer.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_repo_constants_patched_in_tests.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_round_log_decode_boundary.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_round_num_single_source.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_round_result_stable.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_set_diff_for_auto_tool_classification.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_stash_uses_sha_not_index.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_upstream_schema_canary.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/invariants/test_vulture_whitelist_generated.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/literate/__init__.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/literate/parser.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/literate/test_parser.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/literate/test_quickstart.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/__init__.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_agent_runtime.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_agent_runtime_grace.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_agent_runtime_marker_scan.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_agent_runtime_progress.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_agent_runtime_reap.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_agent_runtime_signal_name.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_api_assemble_prompt.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_api_events_stream.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_api_install.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_api_observation.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_api_read_round_num.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_api_resolve_phase.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_api_types.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_auto_stop_gating.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_catalogs.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_claude_error_detector.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_claude_foreign_schema.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_cli.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_cli_common.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_cli_init_install.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_cli_main_boundary.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_cli_monitor_http.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_cli_service_peek_monitor.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_cli_upgrade.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_codewhale_code_precedence.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_codewhale_plugin.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_coerce_int_poison.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_config_fresh_eyes.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_config_max_rounds.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_config_nested_strictness.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_config_prompt_delivery.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_config_schedule.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_config_stop_file.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_config_strictness.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_config_substrate_fingerprint_paths.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_config_transient_error_action.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_context_store.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_control_char_config.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_default_dirty_handler.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_detect_hung_latch.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_detector_isolation.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_detector_protocol.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_dirty_handlers.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_docgen.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_effective_throttle_view.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_emit_config_migrated.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_emit_schedule.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_emit_schedule_phase_skipped.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_events.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_events_cmd.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_events_cmd_rollover.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_events_cmd_tail.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_events_jsonl_decode.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_example_dirty_handler.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_example_plugin.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_exit_cause.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_exit_classifier.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_fresh_eyes_trigger.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_gemini_plugin.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_git_timeout.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_hook_failure_isolation.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_hook_redact_order.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_hooks.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_http_progress.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_init_entry_points.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_interruptible_sleep_should_stop.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_kimi_plugin.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_lifecycle.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_metrics.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_migrate_cmd.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_migrations.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_monitor_assembly.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_monitor_cmd_severity.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_monitor_dedup_identity.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_monitor_detect_anomaly_repetitive.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_monitor_detect_rate_limit.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_monitor_detect_supervisor_stale.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_monitor_detectors.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_monitor_event_tail.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_monitor_round_deferred_stale.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_monitor_schedule_pause.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_network_blip_signal_guard.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_open_round_log.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_orphan_chain_single_pass.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_outer_round_ceiling.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_peek_argparse.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_peek_project_isolation.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_peek_schedule.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_peek_select.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_phase_agent_launch.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_phase_profiles.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_phase_select.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_pi_plugin.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_plugin_constants.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_presets.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_primary_prompt_file_home.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_prompt_loader.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_read_json_hardening.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_redact.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_resolve.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_round_cmd.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_round_cmd_sigterm.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_round_log_helpers.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_round_view.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_runner.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_runner_sidecar_ordering.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_runner_throttle.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_scaffold.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_schedule.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_serve_cmd_bounded.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_serve_config_broken.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_serve_phase_schedule.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_serve_round_log.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_serve_schedule_gate.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_serve_sentinel.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_serve_startup_hooks.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_service_mode.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_startup_battery_exit.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_startup_check.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_substrate.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_supervisor_stale_self_blind.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_throttle_back_off_ladder.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_throttle_plugin_classification.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_upgrade_migrate.py +0 -0
- {cli_agent_runner-0.2.15 → cli_agent_runner-0.2.17}/tests/unit/test_vcs_state.py +0 -0
|
@@ -13,6 +13,13 @@ log_dir
|
|
|
13
13
|
offsets
|
|
14
14
|
buffer
|
|
15
15
|
|
|
16
|
+
# agent_runner._throttle.RoundOutcome
|
|
17
|
+
mem_terminated
|
|
18
|
+
usage_capable
|
|
19
|
+
newest_usage_ts
|
|
20
|
+
newest_substrate_before_ts
|
|
21
|
+
latest_transient_per_agent
|
|
22
|
+
|
|
16
23
|
# agent_runner.agent_runtime.RunResult
|
|
17
24
|
exit_code
|
|
18
25
|
duration_s
|
|
@@ -150,6 +157,10 @@ disk_warning_pct
|
|
|
150
157
|
disk_critical_pct
|
|
151
158
|
swap_sout_noise_floor_mb
|
|
152
159
|
mem_free_low_mb
|
|
160
|
+
psi_full_avg10_critical
|
|
161
|
+
psi_some_avg10_warning
|
|
162
|
+
mem_critical_consecutive_samples
|
|
163
|
+
in_round_mem_terminate
|
|
153
164
|
|
|
154
165
|
# agent_runner.config.models.PhaseOverride
|
|
155
166
|
round_timeout_s
|
|
@@ -5,6 +5,37 @@ 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.2.17] - 2026-09-05
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
- Internal refactor ("round-outcome unification"): per-round classification now does one events-tail scan per round (was up to three), the give-up decision is unified behind a single `post_round_verdicts` (precedence and exit codes `78`/`70`/`71`/`75` unchanged), and the `_serve_round`↔`serve_cmd` import cycle is removed. Behavior-preserving.
|
|
12
|
+
- `round_mem_critical_sample` is now capped at `2 × mem_critical_consecutive_samples` emits per critical episode (any non-critical tick resets it), so a host stuck under sustained pressure no longer writes that calibration event unbounded for a whole round.
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
- Auto-stop no longer records `monitor_auto_stop_failed` for a stop that actually succeeds: under load a round can outlast the stop-confirmation window while draining, which was mis-reported as a failure. The monitor now recognizes a still-draining round and records the real outcome (triggered or failed) once it resolves on the next poll, instead of a false failure.
|
|
16
|
+
|
|
17
|
+
### Notes
|
|
18
|
+
- Not breaking: no `agent-runner migrate`, no systemd unit change, no new event kinds, `peek --json` schema unchanged. The only non-fix behavior change is the bounded `round_mem_critical_sample` above.
|
|
19
|
+
|
|
20
|
+
## [0.2.16] - 2026-09-05
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
- `[monitor.host_health]` gains PSI knobs — `psi_full_avg10_critical` (default 60.0) and `psi_some_avg10_warning` (default 5.0) — plus `mem_critical_consecutive_samples` (default 3) and an `in_round_mem_terminate` off switch for the mid-round memory floor.
|
|
24
|
+
- `serve` probes this process's cgroup v2 memory budget at startup (`host_cgroup_memory_limit`); when `memory.max` and `memory.swap.max` are both finite, the mid-round floor defers to kernel cgroup-OOM (`mem_pressure_deferred_to_cgroup`) instead of terminating the round itself.
|
|
25
|
+
- `mem_loop` now escalates across restarts: recurring 3 times inside a rolling 2h window stops the service for real (`mem_loop_persistent`, exit `70`) instead of respawning into the same loop forever.
|
|
26
|
+
- New exit-0 no-progress breaker: 5 consecutive fast, clean rounds with no recorded usage (a CLI that exits 0 without ever reaching the model) now stop `serve` (`stalled_no_progress`, exit `75`) instead of spinning invisibly.
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
- PSI-full critical was a single ≥1% momentary sample — a hiccup, not a coma — on every PSI-capable host. It now requires a sustained ≥60% avg10 held for `mem_critical_consecutive_samples` (default 3, ~30s) consecutive checks.
|
|
30
|
+
- The mid-round swap-out check is now per-tick instead of cumulative since round-start, so a host that recovers mid-round is no longer permanently flagged for the rest of the round.
|
|
31
|
+
- The pre-round admission gate now defers only on `critical` pressure, not on any pressure (a mere `warning`, e.g. ordinary swap churn, no longer delays the next round).
|
|
32
|
+
|
|
33
|
+
### Notes
|
|
34
|
+
- New events: `host_cgroup_memory_limit`, `mem_pressure_deferred_to_cgroup`, `mem_loop_persistent`, `stalled_no_progress`, `round_mem_critical_sample`; `round_mem_terminated` gained `consecutive`/`context` fields. Not breaking: no `agent-runner migrate` needed, `peek --json` schema is unchanged.
|
|
35
|
+
- Re-render the systemd unit (`agent-runner install`) after upgrading: the new unit adds exit `70` to `RestartPreventExitStatus` so `mem_loop_persistent` stops the service instead of restarting into the same loop.
|
|
36
|
+
|
|
37
|
+
See `docs/migrations/0.2.md`.
|
|
38
|
+
|
|
8
39
|
## [0.2.15] - 2026-09-04
|
|
9
40
|
|
|
10
41
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: cli-agent-runner
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.17
|
|
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
|
|
@@ -94,7 +94,7 @@ Verb reference: [`docs/commands.md`](docs/commands.md).
|
|
|
94
94
|
|
|
95
95
|
## Defenses (built in)
|
|
96
96
|
|
|
97
|
-
|
|
97
|
+
15 named defenses, structured as data — see `agent-runner peek --select defenses`.
|
|
98
98
|
Each carries the historical incident it codifies and the invariant test that
|
|
99
99
|
guards it. Highlights:
|
|
100
100
|
|
|
@@ -58,7 +58,7 @@ Verb reference: [`docs/commands.md`](docs/commands.md).
|
|
|
58
58
|
|
|
59
59
|
## Defenses (built in)
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
15 named defenses, structured as data — see `agent-runner peek --select defenses`.
|
|
62
62
|
Each carries the historical incident it codifies and the invariant test that
|
|
63
63
|
guards it. Highlights:
|
|
64
64
|
|
|
@@ -19,13 +19,17 @@ __all__ = [
|
|
|
19
19
|
"emit_anomaly_repetitive_tool",
|
|
20
20
|
"emit_config_migrated",
|
|
21
21
|
"emit_fresh_eyes_round_triggered",
|
|
22
|
+
"emit_host_cgroup_memory_limit",
|
|
22
23
|
"emit_max_rounds_reached",
|
|
23
24
|
"emit_mem_loop",
|
|
25
|
+
"emit_mem_loop_persistent",
|
|
26
|
+
"emit_mem_pressure_deferred_to_cgroup",
|
|
24
27
|
"emit_rate_limit_stop",
|
|
25
28
|
"emit_round_deferred",
|
|
26
29
|
"emit_round_grace_extended",
|
|
27
30
|
"emit_round_grace_kill",
|
|
28
31
|
"emit_round_logs_prune_deferred",
|
|
32
|
+
"emit_round_mem_critical_sample",
|
|
29
33
|
"emit_round_mem_terminated",
|
|
30
34
|
"emit_round_progress",
|
|
31
35
|
"emit_round_resumed",
|
|
@@ -36,6 +40,7 @@ __all__ = [
|
|
|
36
40
|
"emit_schedule_phase_skipped",
|
|
37
41
|
"emit_schedule_resumed",
|
|
38
42
|
"emit_stale_index_lock_cleared",
|
|
43
|
+
"emit_stalled_no_progress",
|
|
39
44
|
"emit_stop_file_detected",
|
|
40
45
|
"emit_transient_error_backoff_capped",
|
|
41
46
|
"emit_transient_error_detected",
|
|
@@ -110,6 +115,60 @@ def emit_mem_loop(log_dir: Path, *, consecutive: int, exit_code: int, log_path:
|
|
|
110
115
|
_emit_giveup(log_dir, MEM_LOOP, consecutive=consecutive, exit_code=exit_code, log_path=log_path)
|
|
111
116
|
|
|
112
117
|
|
|
118
|
+
def emit_mem_loop_persistent(
|
|
119
|
+
log_dir: Path, *, consecutive: int, exit_code: int, log_path: Path
|
|
120
|
+
) -> None:
|
|
121
|
+
"""Emit mem_loop_persistent (serve STOPS for real — 0.2.16 Task 5 cross-restart
|
|
122
|
+
convergence: mem_loop itself kept recurring across restarts within the
|
|
123
|
+
escalation window, so systemd is told to stop rather than respawn into the
|
|
124
|
+
identical loop forever). Distinct from mem_loop: this IS a deliberate stop,
|
|
125
|
+
like crash_loop/config_broken, so it belongs in the unit's
|
|
126
|
+
RestartPreventExitStatus.
|
|
127
|
+
|
|
128
|
+
``consecutive`` counts mem_loop EPISODES within the persistence window
|
|
129
|
+
(up to ``_serve_policy._MEM_LOOP_PERSIST_THRESHOLD``) — NOT mid-round
|
|
130
|
+
terminations within one episode, which is mem_loop's own ``consecutive``
|
|
131
|
+
(up to ``MEM_LOOP_THRESHOLD``). Same redacted-log-tail reason capture as
|
|
132
|
+
crash_loop/mem_loop."""
|
|
133
|
+
from agent_runner.events import MEM_LOOP_PERSISTENT
|
|
134
|
+
|
|
135
|
+
_emit_giveup(
|
|
136
|
+
log_dir,
|
|
137
|
+
MEM_LOOP_PERSISTENT,
|
|
138
|
+
consecutive=consecutive,
|
|
139
|
+
exit_code=exit_code,
|
|
140
|
+
log_path=log_path,
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def emit_stalled_no_progress(
|
|
145
|
+
log_dir: Path, *, consecutive: int, exit_code: int, log_path: Path
|
|
146
|
+
) -> None:
|
|
147
|
+
"""Emit stalled_no_progress (serve gave up after consecutive clean-but-
|
|
148
|
+
no-progress rounds -- 0.2.16 Task 6). A round that exits 0 fast with no
|
|
149
|
+
``agent_usage_recorded`` never reached the model (pi, and CLIs like it,
|
|
150
|
+
exit 0 on a provider failure) -- ``_round_ok = exit_code == 0``
|
|
151
|
+
(api_types.py) reads that as clean, so without this breaker it is a fast,
|
|
152
|
+
invisible, unclassified-failure spin, no different in kind from an
|
|
153
|
+
unknown short crash except for the exit code it hides behind.
|
|
154
|
+
|
|
155
|
+
Deliberately reuses ``CRASH_LOOP_EXIT`` (75), not a new exit code: this is
|
|
156
|
+
the SAME give-up verdict as crash_loop ("an unknown failure kept
|
|
157
|
+
recurring, stop for real") reached via a different signal (no usage
|
|
158
|
+
instead of a non-zero exit) -- not a new failure class, so it needs no new
|
|
159
|
+
entry in the systemd unit's ``RestartPreventExitStatus``. Same redacted-
|
|
160
|
+
log-tail reason capture as crash_loop/mem_loop."""
|
|
161
|
+
from agent_runner.events import STALLED_NO_PROGRESS
|
|
162
|
+
|
|
163
|
+
_emit_giveup(
|
|
164
|
+
log_dir,
|
|
165
|
+
STALLED_NO_PROGRESS,
|
|
166
|
+
consecutive=consecutive,
|
|
167
|
+
exit_code=exit_code,
|
|
168
|
+
log_path=log_path,
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
|
|
113
172
|
def emit_config_migrated(
|
|
114
173
|
log_dir: Path, *, applied: list[str], manual: list[str], path: str
|
|
115
174
|
) -> None:
|
|
@@ -202,15 +261,106 @@ def emit_round_resumed(log_dir: Path, *, deferred_for_s: int) -> None:
|
|
|
202
261
|
|
|
203
262
|
|
|
204
263
|
def emit_round_mem_terminated(
|
|
205
|
-
log_dir: Path,
|
|
264
|
+
log_dir: Path,
|
|
265
|
+
*,
|
|
266
|
+
pid: int,
|
|
267
|
+
severity: str,
|
|
268
|
+
signal: str,
|
|
269
|
+
message: str,
|
|
270
|
+
consecutive: int,
|
|
271
|
+
context: dict,
|
|
206
272
|
) -> None:
|
|
207
273
|
"""Emit when _spawn_round's mid-round hard floor terminated a ballooning
|
|
208
274
|
round on critical host_health pressure -- the actual coma-preventer (a
|
|
209
275
|
pre-round-only gate can't stop a single round mid-flight). Distinct from
|
|
210
|
-
round_supervisor_wedged (a wall-clock ceiling breach, unrelated cause).
|
|
276
|
+
round_supervisor_wedged (a wall-clock ceiling breach, unrelated cause).
|
|
277
|
+
|
|
278
|
+
0.2.16: ``consecutive`` (the critical_streak that crossed the threshold)
|
|
279
|
+
and ``context`` (Pressure.context -- the actual psi/mem numbers, e.g.
|
|
280
|
+
psi_full_avg10) make the kill legible from the event stream alone, so an
|
|
281
|
+
operator can retune host_health thresholds without SSH."""
|
|
211
282
|
from agent_runner.events import ROUND_MEM_TERMINATED, emit
|
|
212
283
|
|
|
213
|
-
emit(
|
|
284
|
+
emit(
|
|
285
|
+
log_dir,
|
|
286
|
+
ROUND_MEM_TERMINATED,
|
|
287
|
+
pid=pid,
|
|
288
|
+
severity=severity,
|
|
289
|
+
signal=signal,
|
|
290
|
+
message=message,
|
|
291
|
+
consecutive=consecutive,
|
|
292
|
+
context=context,
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
def emit_round_mem_critical_sample(
|
|
297
|
+
log_dir: Path, *, round_num: int, consecutive: int, context: dict
|
|
298
|
+
) -> None:
|
|
299
|
+
"""Emit on each critical host_health sample inside _spawn_round's mid-round
|
|
300
|
+
hard floor, up to the per-episode cap (0.2.17, below) -- unlike
|
|
301
|
+
round_mem_terminated (deduped to once-per-episode), this fires on every
|
|
302
|
+
critical tick within that cap: the point is calibration visibility into
|
|
303
|
+
near-misses, so an operator watching the event stream sees the
|
|
304
|
+
critical_streak build (1, 2, ...) even on ticks that never reach the
|
|
305
|
+
terminate threshold (a healthy tick resets it before 3-in-a-row).
|
|
306
|
+
``context`` carries the same Pressure.context numbers as
|
|
307
|
+
round_mem_terminated. Fires only during critical pressure -- never during
|
|
308
|
+
warning/healthy -- so it adds no normal-operation noise, including while
|
|
309
|
+
``defer_to_cgroup`` steps back from terminating (the streak/context is
|
|
310
|
+
still useful calibration there; this event stays scoped to the
|
|
311
|
+
sample-level signal, distinct from mem_pressure_deferred_to_cgroup's
|
|
312
|
+
once-per-episode terminate-vs-defer notice).
|
|
313
|
+
|
|
314
|
+
0.2.17: the caller caps this at ``2 * mem_critical_consecutive_samples``
|
|
315
|
+
consecutive ticks (1..6 at the default 3) -- a sustained-critical
|
|
316
|
+
don't-terminate run (cgroup-defer, or the off switch) would otherwise
|
|
317
|
+
write one event per ~10s tick for up to a whole ``round_timeout_s`` on a
|
|
318
|
+
permanently-deferred/off host. The cap is per streak-episode, not a
|
|
319
|
+
lifetime limit: any non-critical tick still resets the streak to 0, and
|
|
320
|
+
sampling resumes from 1 the next time critical pressure recurs."""
|
|
321
|
+
from agent_runner.events import ROUND_MEM_CRITICAL_SAMPLE, emit
|
|
322
|
+
|
|
323
|
+
emit(
|
|
324
|
+
log_dir,
|
|
325
|
+
ROUND_MEM_CRITICAL_SAMPLE,
|
|
326
|
+
round_num=round_num,
|
|
327
|
+
consecutive=consecutive,
|
|
328
|
+
context=context,
|
|
329
|
+
)
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
def emit_host_cgroup_memory_limit(
|
|
333
|
+
log_dir: Path, *, memory_max: int | None, memory_swap_max: int | None, cgroup_path: str | None
|
|
334
|
+
) -> None:
|
|
335
|
+
"""Emit once at serve startup: this process's cgroup v2 memory budget
|
|
336
|
+
(``metrics.cgroup_memory_limits``). ``None`` fields mean unlimited (or
|
|
337
|
+
cgroup v2 unavailable). Serve uses this once to decide whether the
|
|
338
|
+
mid-round hard floor can defer to kernel cgroup-OOM -- see
|
|
339
|
+
``emit_mem_pressure_deferred_to_cgroup`` below."""
|
|
340
|
+
from agent_runner.events import HOST_CGROUP_MEMORY_LIMIT, emit
|
|
341
|
+
|
|
342
|
+
emit(
|
|
343
|
+
log_dir,
|
|
344
|
+
HOST_CGROUP_MEMORY_LIMIT,
|
|
345
|
+
memory_max=memory_max,
|
|
346
|
+
memory_swap_max=memory_swap_max,
|
|
347
|
+
cgroup_path=cgroup_path,
|
|
348
|
+
)
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
def emit_mem_pressure_deferred_to_cgroup(
|
|
352
|
+
log_dir: Path, *, pid: int, signal: str, message: str
|
|
353
|
+
) -> None:
|
|
354
|
+
"""Emit when _spawn_round's mid-round hard floor hits sustained critical
|
|
355
|
+
pressure but this cgroup's (mem+swap) budget is bounded end to end
|
|
356
|
+
(both memory.max and memory.swap.max finite) -- kernel cgroup-OOM will
|
|
357
|
+
contain the agent and keep the host responsive on its own, so the
|
|
358
|
+
cruder host-wide round-kill steps back instead of firing
|
|
359
|
+
round_mem_terminated. This OVERRIDES in_round_mem_terminate=True: a
|
|
360
|
+
bounded cgroup makes the host floor strictly worse, not just redundant."""
|
|
361
|
+
from agent_runner.events import MEM_PRESSURE_DEFERRED_TO_CGROUP, emit
|
|
362
|
+
|
|
363
|
+
emit(log_dir, MEM_PRESSURE_DEFERRED_TO_CGROUP, pid=pid, signal=signal, message=message)
|
|
214
364
|
|
|
215
365
|
|
|
216
366
|
def emit_round_substrate_before(
|
|
@@ -54,6 +54,46 @@ MEM_LOOP_EXIT = 71
|
|
|
54
54
|
# Consecutive mem-terminated rounds before serve gives up (break-then-restart).
|
|
55
55
|
MEM_LOOP_THRESHOLD = 5
|
|
56
56
|
|
|
57
|
+
# Exit code for mem_loop's cross-restart escalation (0.2.16 Task 5 — field
|
|
58
|
+
# confirmed: NRestarts climbs, never converges). MEM_LOOP_EXIT (71) alone
|
|
59
|
+
# resets on every process restart, so a host stuck in sustained pressure
|
|
60
|
+
# respawns into the identical break-then-restart loop forever. Once mem_loop
|
|
61
|
+
# itself keeps recurring across restarts (see _MEM_LOOP_PERSIST_THRESHOLD),
|
|
62
|
+
# this is a DELIBERATE stop instead — "gave up for real, needs a human" — so,
|
|
63
|
+
# unlike 71, it IS listed in the unit's RestartPreventExitStatus. 70 =
|
|
64
|
+
# EX_SOFTWARE (sysexits); verified free (grep -rnE "= 70\b|code=70\b").
|
|
65
|
+
MEM_LOOP_PERSISTENT_EXIT = 70
|
|
66
|
+
|
|
67
|
+
# Escalation window/threshold for the cross-restart convergence above: prior
|
|
68
|
+
# mem_loop events are counted only within the last _MEM_LOOP_PERSIST_WINDOW_S
|
|
69
|
+
# seconds (2h) of "now" — old episodes age out on their own, so a host that
|
|
70
|
+
# stays healthy for a sustained window earns a fresh restartable 71 again
|
|
71
|
+
# instead of ratcheting toward the persistent stop forever (no state file:
|
|
72
|
+
# purely events-tail derived, restart-safe by construction). Once this run's
|
|
73
|
+
# mem_loop would be the _MEM_LOOP_PERSIST_THRESHOLD-th (3rd) occurrence inside
|
|
74
|
+
# the window (~2 prior + this one, ⇒ ~15 mem-terminated kills total), serve
|
|
75
|
+
# escalates to MEM_LOOP_PERSISTENT_EXIT instead of the usual 71.
|
|
76
|
+
_MEM_LOOP_PERSIST_WINDOW_S = 7200
|
|
77
|
+
_MEM_LOOP_PERSIST_THRESHOLD = 3
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
# Exit-0 no-progress breaker (0.2.16 Task 6). Some CLIs (pi -- see
|
|
81
|
+
# builtin_plugins/pi.py's "pi exits 0 on provider failure") exit 0 on a
|
|
82
|
+
# provider failure that never reaches the model: `_round_ok = exit_code == 0`
|
|
83
|
+
# (api_types.py) reads that as a clean round, so without this breaker an
|
|
84
|
+
# invalid credential (or an exhausted-retries outage) spins as a fast,
|
|
85
|
+
# invisible "success" loop with no breaker, no back-off, and no alert -- on a
|
|
86
|
+
# constrained host, that tight loop is itself a memory-pressure generator.
|
|
87
|
+
# "No progress" = exit 0, a SHORT round (< _NO_PROGRESS_SHORT_S), and no
|
|
88
|
+
# agent_usage_recorded for it (see _throttle.round_had_no_progress for the
|
|
89
|
+
# events-derived scoping). Deliberately reuses CRASH_LOOP_THRESHOLD /
|
|
90
|
+
# CRASH_LOOP_EXIT rather than minting new ones: this is the SAME give-up
|
|
91
|
+
# verdict as the crash-loop breaker ("an unknown failure kept recurring, stop
|
|
92
|
+
# for real"), reached via a different signal (no usage instead of a non-zero
|
|
93
|
+
# exit) -- not a new failure class needing its own systemd
|
|
94
|
+
# RestartPreventExitStatus entry.
|
|
95
|
+
_NO_PROGRESS_SHORT_S = 30
|
|
96
|
+
|
|
57
97
|
|
|
58
98
|
class EnvironmentalError(Exception):
|
|
59
99
|
"""Marks a round-child failure as ENVIRONMENTAL (recoverable) rather than a
|
|
@@ -117,6 +157,25 @@ def post_round_decision(
|
|
|
117
157
|
return ("continue", delay, 0)
|
|
118
158
|
|
|
119
159
|
|
|
160
|
+
def _consecutive_streak_decision(
|
|
161
|
+
*, triggered: bool, consecutive: int, threshold: int, verdict: str
|
|
162
|
+
) -> tuple[str, int]:
|
|
163
|
+
"""The generic give-up-cap shape both :func:`_mem_loop_decision` and
|
|
164
|
+
:func:`_no_progress_decision` delegate to (0.2.17 Task 2 — de-duplicated
|
|
165
|
+
out of the two, which were byte-identical apart from their reset
|
|
166
|
+
condition, threshold constant, and verdict string). A NEW, SEPARATE,
|
|
167
|
+
private counter from ``post_round_decision``'s crash-loop breaker, not a
|
|
168
|
+
widening of its 3-tuple contract. Returns ``(verdict, consecutive)`` once
|
|
169
|
+
``consecutive`` reaches ``threshold``; a non-``triggered`` round resets the
|
|
170
|
+
counter to 0."""
|
|
171
|
+
if not triggered:
|
|
172
|
+
return ("continue", 0)
|
|
173
|
+
consecutive += 1
|
|
174
|
+
if consecutive >= threshold:
|
|
175
|
+
return (verdict, consecutive)
|
|
176
|
+
return ("continue", consecutive)
|
|
177
|
+
|
|
178
|
+
|
|
120
179
|
def _mem_loop_decision(
|
|
121
180
|
*, mem_terminated: bool, consecutive: int
|
|
122
181
|
) -> tuple[Literal["mem_loop", "continue"], int]:
|
|
@@ -128,12 +187,34 @@ def _mem_loop_decision(
|
|
|
128
187
|
eventually giving up. Returns ``("mem_loop", consecutive)`` once
|
|
129
188
|
``consecutive`` reaches ``MEM_LOOP_THRESHOLD``; a non-mem-terminated round
|
|
130
189
|
resets the counter to 0, same reset shape as the crash-loop breaker."""
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
190
|
+
return _consecutive_streak_decision(
|
|
191
|
+
triggered=mem_terminated,
|
|
192
|
+
consecutive=consecutive,
|
|
193
|
+
threshold=MEM_LOOP_THRESHOLD,
|
|
194
|
+
verdict="mem_loop",
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def _no_progress_decision(
|
|
199
|
+
*, no_progress: bool, consecutive: int
|
|
200
|
+
) -> tuple[Literal["stalled_no_progress", "continue"], int]:
|
|
201
|
+
"""Exit-0 no-progress give-up cap (0.2.16 Task 6) -- a NEW, SEPARATE,
|
|
202
|
+
private counter from ``post_round_decision``'s crash-loop breaker (that one
|
|
203
|
+
keys on ``returncode != 0``; here returncode IS 0, so a round that never
|
|
204
|
+
reached the model would otherwise sail through with no breaker at all).
|
|
205
|
+
Same shape as :func:`_mem_loop_decision`: returns ``("stalled_no_progress",
|
|
206
|
+
consecutive)`` once ``consecutive`` reaches ``CRASH_LOOP_THRESHOLD`` --
|
|
207
|
+
reusing that threshold (and, at the call site, ``CRASH_LOOP_EXIT``) rather
|
|
208
|
+
than minting new ones, since this is the identical give-up verdict reached
|
|
209
|
+
via a different signal. A round WITH progress (usage recorded, non-zero
|
|
210
|
+
exit, or slow) resets the counter to 0, same reset shape as
|
|
211
|
+
crash-loop/mem-loop."""
|
|
212
|
+
return _consecutive_streak_decision(
|
|
213
|
+
triggered=no_progress,
|
|
214
|
+
consecutive=consecutive,
|
|
215
|
+
threshold=CRASH_LOOP_THRESHOLD,
|
|
216
|
+
verdict="stalled_no_progress",
|
|
217
|
+
)
|
|
137
218
|
|
|
138
219
|
|
|
139
220
|
def classify_round_exit(exc: BaseException) -> int:
|
|
@@ -194,7 +275,7 @@ def classify_round_exit(exc: BaseException) -> int:
|
|
|
194
275
|
_REAP_GRACE_S = 5
|
|
195
276
|
_GIT_COMMIT_TIMEOUT_S = 120
|
|
196
277
|
_HOOK_ALLOWANCE_S = 60 # slack for post-round hooks between the inner wall and the ceiling
|
|
197
|
-
_ROUND_TERM_GRACE_S = 15 # mirrors api._ROUND_TERM_GRACE_S /
|
|
278
|
+
_ROUND_TERM_GRACE_S = 15 # mirrors api._ROUND_TERM_GRACE_S / cli._serve_round._ROUND_TERM_GRACE_S
|
|
198
279
|
_STOP_GRACE_MARGIN_S = 10 # pad above _ROUND_TERM_GRACE_S for systemd stop-request overhead
|
|
199
280
|
|
|
200
281
|
|