cli-agent-runner 0.2.10__tar.gz → 0.2.12__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.10 → cli_agent_runner-0.2.12}/.vulture-whitelist.py +6 -1
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/CHANGELOG.md +37 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/PKG-INFO +1 -1
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/_docgen.py +9 -4
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/_emit.py +23 -0
- cli_agent_runner-0.2.12/agent_runner/_serve_policy.py +89 -0
- cli_agent_runner-0.2.12/agent_runner/_throttle.py +551 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/_version.py +2 -2
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/agent_runtime.py +74 -51
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/api.py +153 -87
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/api_types.py +14 -6
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/builtin_plugins/_constants.py +6 -3
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/builtin_plugins/claude_rate_limit.py +66 -18
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/builtin_plugins/codewhale.py +9 -9
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/cli/__init__.py +14 -1
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/cli/common.py +1 -1
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/cli/events_cmd.py +26 -17
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/cli/monitor_cmd.py +3 -1
- cli_agent_runner-0.2.12/agent_runner/cli/round_cmd.py +54 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/cli/serve_cmd.py +294 -73
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/cli/service_cmd.py +6 -5
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/cli/upgrade_cmd.py +81 -8
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/config.py +90 -11
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/context_store.py +4 -3
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/defenses.py +3 -2
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/events.py +4 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/hooks.py +18 -12
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/http_progress.py +2 -2
- cli_agent_runner-0.2.12/agent_runner/lifecycle.py +108 -0
- cli_agent_runner-0.2.12/agent_runner/migrations.py +401 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/monitor.py +179 -51
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/phase_select.py +8 -1
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/round_log.py +54 -6
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/round_view.py +3 -1
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/runner.py +48 -68
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/scaffold.py +5 -2
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/service_unit.py +14 -1
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/startup_check.py +50 -9
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/vcs_state.py +88 -15
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/docs/architecture.md +4 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/docs/commands.md +23 -1
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/docs/configuration.md +12 -8
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/docs/migrations/0.2.md +72 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/docs/plugins.md +4 -3
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/docs/runbook.md +32 -19
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/_clock.py +5 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/_test_helpers.py +7 -1
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/contract/test_public_api_surface.py +132 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/integration/test_fresh_eyes_signal.py +13 -12
- cli_agent_runner-0.2.12/tests/integration/test_spawn_round_wedged.py +92 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/integration/test_substrate_fingerprint.py +4 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/integration/test_transient_error_backoff.py +3 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/invariants/test_architecture.py +17 -3
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/invariants/test_atomic_write_enforced.py +3 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/invariants/test_doc_test_pointers_exist.py +14 -1
- cli_agent_runner-0.2.12/tests/invariants/test_event_int_coercion.py +56 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/invariants/test_event_kinds_ssot.py +1 -1
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/invariants/test_module_boundaries.py +48 -37
- cli_agent_runner-0.2.12/tests/invariants/test_monitor_self_exclusion.py +22 -0
- cli_agent_runner-0.2.12/tests/invariants/test_no_vacuous_invariants.py +43 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/invariants/test_peek_schema_version.py +7 -2
- cli_agent_runner-0.2.12/tests/invariants/test_round_log_decode_boundary.py +45 -0
- cli_agent_runner-0.2.12/tests/invariants/test_round_num_single_source.py +43 -0
- cli_agent_runner-0.2.12/tests/invariants/test_stash_uses_sha_not_index.py +78 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_agent_runtime_grace.py +42 -5
- cli_agent_runner-0.2.12/tests/unit/test_agent_runtime_marker_scan.py +84 -0
- cli_agent_runner-0.2.12/tests/unit/test_agent_runtime_reap.py +64 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_api_observation.py +96 -1
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_api_service.py +100 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_api_types.py +25 -0
- cli_agent_runner-0.2.12/tests/unit/test_claude_foreign_schema.py +133 -0
- cli_agent_runner-0.2.12/tests/unit/test_cli_main_boundary.py +27 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_cli_service_peek_monitor.py +29 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_cli_upgrade.py +220 -60
- cli_agent_runner-0.2.12/tests/unit/test_codewhale_code_precedence.py +17 -0
- cli_agent_runner-0.2.12/tests/unit/test_coerce_int_poison.py +94 -0
- cli_agent_runner-0.2.12/tests/unit/test_config_strictness.py +96 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_context_store.py +11 -0
- cli_agent_runner-0.2.12/tests/unit/test_detect_hung_latch.py +31 -0
- cli_agent_runner-0.2.12/tests/unit/test_detector_isolation.py +25 -0
- cli_agent_runner-0.2.12/tests/unit/test_effective_throttle_view.py +68 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_events.py +1 -1
- cli_agent_runner-0.2.12/tests/unit/test_events_cmd_rollover.py +42 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_exit_cause.py +10 -2
- cli_agent_runner-0.2.12/tests/unit/test_git_timeout.py +139 -0
- cli_agent_runner-0.2.12/tests/unit/test_hook_redact_order.py +33 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_http_progress.py +48 -0
- cli_agent_runner-0.2.12/tests/unit/test_interruptible_sleep_should_stop.py +47 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_lifecycle.py +53 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_migrate_cmd.py +13 -0
- cli_agent_runner-0.2.12/tests/unit/test_migrations.py +203 -0
- cli_agent_runner-0.2.12/tests/unit/test_monitor_cmd_severity.py +19 -0
- cli_agent_runner-0.2.12/tests/unit/test_monitor_dedup_identity.py +125 -0
- cli_agent_runner-0.2.12/tests/unit/test_monitor_dedup_rearm.py +42 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_monitor_detectors.py +19 -0
- cli_agent_runner-0.2.12/tests/unit/test_monitor_event_tail.py +20 -0
- cli_agent_runner-0.2.12/tests/unit/test_open_round_log.py +24 -0
- cli_agent_runner-0.2.12/tests/unit/test_orphan_chain_single_pass.py +26 -0
- cli_agent_runner-0.2.12/tests/unit/test_outer_round_ceiling.py +39 -0
- cli_agent_runner-0.2.12/tests/unit/test_peek_project_isolation.py +38 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_phase_select.py +19 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_plugin_constants.py +20 -0
- cli_agent_runner-0.2.12/tests/unit/test_primary_prompt_file_home.py +23 -0
- cli_agent_runner-0.2.12/tests/unit/test_round_cmd.py +57 -0
- cli_agent_runner-0.2.12/tests/unit/test_round_cmd_sigterm.py +33 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_round_log_helpers.py +88 -0
- cli_agent_runner-0.2.12/tests/unit/test_runner_sidecar_ordering.py +34 -0
- cli_agent_runner-0.2.12/tests/unit/test_runner_throttle.py +654 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_scaffold.py +29 -0
- cli_agent_runner-0.2.12/tests/unit/test_serve_config_broken.py +47 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_serve_crash_loop.py +41 -19
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_serve_phase_schedule.py +132 -34
- cli_agent_runner-0.2.12/tests/unit/test_serve_policy.py +29 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_serve_round_log.py +15 -24
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_serve_schedule_gate.py +7 -4
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_serve_sentinel.py +30 -30
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_serve_startup_hooks.py +4 -8
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_service_unit.py +21 -1
- cli_agent_runner-0.2.12/tests/unit/test_startup_battery_exit.py +52 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_startup_check.py +38 -0
- cli_agent_runner-0.2.12/tests/unit/test_supervisor_stale_self_blind.py +31 -0
- cli_agent_runner-0.2.12/tests/unit/test_throttle_back_off_ladder.py +95 -0
- cli_agent_runner-0.2.10/agent_runner/_throttle.py +0 -220
- cli_agent_runner-0.2.10/agent_runner/cli/round_cmd.py +0 -25
- cli_agent_runner-0.2.10/agent_runner/lifecycle.py +0 -67
- cli_agent_runner-0.2.10/agent_runner/migrations.py +0 -115
- cli_agent_runner-0.2.10/tests/invariants/test_stash_uses_sha_not_index.py +0 -21
- cli_agent_runner-0.2.10/tests/unit/test_migrations.py +0 -83
- cli_agent_runner-0.2.10/tests/unit/test_runner_throttle.py +0 -427
- cli_agent_runner-0.2.10/tests/unit/test_serve_config_broken.py +0 -33
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/.codecov.yml +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/.github/workflows/ci.yml +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/.github/workflows/release.yml +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/.gitignore +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/BACKLOG.md +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/CODE_OF_CONDUCT.md +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/CONTRIBUTING.md +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/LICENSE +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/README.md +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/README.zh.md +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/SECURITY.md +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/__init__.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/_redact.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/_registry.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/_substrate.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/builtin_plugins/__init__.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/builtin_plugins/default_dirty_handler.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/builtin_plugins/gemini.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/builtin_plugins/kimi.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/builtin_plugins/pi.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/cli/__main__.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/cli/init_cmd.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/cli/install_cmd.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/cli/migrate_cmd.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/cli/peek_cmd.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/clock.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/metrics.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/presets/__init__.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/presets/aider.toml +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/presets/claude.toml +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/presets/codewhale.toml +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/presets/gemini.toml +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/presets/kimi.toml +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/presets/pi.toml +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/prompt_loader.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/remote_relay.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/agent_runner/schedule.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/build.sh +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/docs/README.md +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/docs/events.md +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/docs/long-running-agents.md +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/docs/quickstart.md +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/docs/recipes/aider.md +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/docs/recipes/codewhale.md +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/docs/recipes/kimi.md +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/docs/recipes/pi.md +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/docs/thesis.md +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/pyproject.toml +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/__init__.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/conftest.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/contract/__init__.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/e2e/__init__.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/e2e/conftest.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/e2e/test_e2e_graceful_stop.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/e2e/test_e2e_install_systemd.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/e2e/test_e2e_monitor_remote.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/e2e/test_e2e_round_lifecycle.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/fixtures/cli-real-output/claude-2.1.143-assistant-tool-use.jsonl +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/fixtures/cli-real-output/claude-2.1.143-result-event.jsonl +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/fixtures/cli-real-output/gemini-0.42.0-result-event.jsonl +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/generate_vulture_whitelist.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/integration/__init__.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/integration/test_bounded_run.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/integration/test_context_enricher_namespacing.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/integration/test_dirty_handler_seam.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/integration/test_grace_kill_emission.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/integration/test_install_dry_run.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/integration/test_monitor_seeded.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/integration/test_plugin_detector_loaded.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/integration/test_plugin_owned_paths.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/integration/test_plugin_real_flow.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/integration/test_prompt_delivery_stdin.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/integration/test_run_one_round_with_fake_agent.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/integration/test_scaffold_presets.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/integration/test_serve_loop.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/invariants/__init__.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/invariants/_docs.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/invariants/_event_scan.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/invariants/test_authored_facts_declared.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/invariants/test_auto_stop_policy_ssot.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/invariants/test_catalogs.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/invariants/test_classification_ssot.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/invariants/test_config_error_consistency.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/invariants/test_config_value_set_ssot.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/invariants/test_doc_builtin_plugins.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/invariants/test_doc_claims_match_ssot.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/invariants/test_doc_cli_claims.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/invariants/test_doc_operator_surface.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/invariants/test_doc_transient_error_claims.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/invariants/test_doc_usage_event_fields.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/invariants/test_docs_generated.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/invariants/test_docs_index_complete.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/invariants/test_entry_points_resolve.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/invariants/test_event_kind_registry.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/invariants/test_events_doc_contract.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/invariants/test_gen_blocks_name_their_source.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/invariants/test_hook_contract_docs.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/invariants/test_layer_2_loop_size.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/invariants/test_module_sizes.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/invariants/test_no_ai_signatures.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/invariants/test_no_pytest_skip_on_parse_fail.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/invariants/test_no_raw_time.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/invariants/test_phase_select_stateless.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/invariants/test_plugins_config_stable.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/invariants/test_readme_zh_is_pointer.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/invariants/test_repo_constants_patched_in_tests.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/invariants/test_round_result_stable.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/invariants/test_set_diff_for_auto_tool_classification.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/invariants/test_upstream_schema_canary.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/invariants/test_vulture_whitelist_generated.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/literate/__init__.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/literate/parser.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/literate/test_parser.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/literate/test_quickstart.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/__init__.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_agent_runtime.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_agent_runtime_progress.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_agent_runtime_signal_name.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_api_assemble_prompt.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_api_events_stream.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_api_install.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_api_read_round_num.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_api_resolve_phase.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_auto_stop_gating.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_catalogs.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_claude_error_detector.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_cli.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_cli_common.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_cli_init_install.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_cli_monitor_http.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_codewhale_plugin.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_config.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_config_fresh_eyes.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_config_max_rounds.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_config_prompt_delivery.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_config_schedule.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_config_stop_file.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_config_substrate_fingerprint_paths.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_config_transient_error_action.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_default_dirty_handler.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_defenses.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_detector_protocol.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_dirty_handlers.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_docgen.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_emit_config_migrated.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_emit_schedule.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_emit_schedule_phase_skipped.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_events_cmd.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_events_cmd_tail.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_example_dirty_handler.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_example_plugin.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_fresh_eyes_trigger.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_gemini_plugin.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_hook_failure_isolation.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_hooks.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_init_entry_points.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_kimi_plugin.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_metrics.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_monitor_assembly.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_monitor_detect_anomaly_repetitive.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_monitor_detect_rate_limit.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_monitor_detect_supervisor_stale.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_monitor_remote.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_monitor_schedule_pause.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_network_blip_signal_guard.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_peek_argparse.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_peek_schedule.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_peek_select.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_phase_agent_launch.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_phase_profiles.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_pi_plugin.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_presets.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_prompt_loader.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_redact.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_round_view.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_runner.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_schedule.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_serve_cmd_bounded.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_substrate.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_throttle_plugin_classification.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_upgrade_migrate.py +0 -0
- {cli_agent_runner-0.2.10 → cli_agent_runner-0.2.12}/tests/unit/test_vcs_state.py +0 -0
|
@@ -12,7 +12,6 @@ duration_s
|
|
|
12
12
|
timed_out
|
|
13
13
|
pid
|
|
14
14
|
killed_for_grace
|
|
15
|
-
grace_kill_children
|
|
16
15
|
|
|
17
16
|
# agent_runner.api_types.Alert
|
|
18
17
|
severity
|
|
@@ -58,6 +57,7 @@ limit_type
|
|
|
58
57
|
agent
|
|
59
58
|
since_round
|
|
60
59
|
phase
|
|
60
|
+
throttled_agents
|
|
61
61
|
|
|
62
62
|
# agent_runner.api_types.RoundResult
|
|
63
63
|
round_num
|
|
@@ -256,6 +256,10 @@ manual
|
|
|
256
256
|
# agent_runner.monitor.LocalSource
|
|
257
257
|
log_dir
|
|
258
258
|
|
|
259
|
+
# agent_runner.monitor._EventTail
|
|
260
|
+
offsets
|
|
261
|
+
buffer
|
|
262
|
+
|
|
259
263
|
# agent_runner.phase_select.Selection
|
|
260
264
|
phase
|
|
261
265
|
paused
|
|
@@ -286,6 +290,7 @@ name
|
|
|
286
290
|
ok
|
|
287
291
|
reason
|
|
288
292
|
how_to_fix
|
|
293
|
+
permanent
|
|
289
294
|
|
|
290
295
|
# agent_runner.vcs_state.StashRef
|
|
291
296
|
sha
|
|
@@ -5,6 +5,43 @@ 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.12] - 2026-08-31
|
|
9
|
+
|
|
10
|
+
### Breaking
|
|
11
|
+
- Config validation now hard-rejects footguns that used to load silently: a scalar where a list is required (`phases.list`, `[agent] command`, `prompt_arg_template`, `[prompt] files`), an empty `[agent] command` / empty top-level `[prompt] files`, unknown keys in `[schedule]`/`[prompt]`, and `threshold > window`. **Run `agent-runner migrate` BEFORE `upgrade`** — the orchestrated upgrade runs the old binary's migrate, which cannot self-cross this break. Every new error names `agent-runner migrate`.
|
|
12
|
+
- systemd `serve` unit adds `StartLimitIntervalSec`/`StartLimitBurst`; re-render or hand-edit existing units.
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
- The monitor no longer dies on a non-UTF-8 byte or an odd plugin severity; each builtin detector is isolated (`detector_error` event) and a hung round is TERM→grace→killpg'd (`round_supervisor_wedged`) instead of orphaning the agent or latching `hung`.
|
|
16
|
+
- Environmental startup failures (ENOSPC, mount hiccup, unclassified) exit 76 and keep serve retrying at a fixed back-off until they heal, instead of tripping the crash-loop breaker; deterministic config failures give up by name (exit 78).
|
|
17
|
+
- A git-commit timeout leaves no surviving `.git/index.lock` (self-caused only; `stale_index_lock_cleared`); a stop-file lands within one back-off chunk.
|
|
18
|
+
- `status`/`kill`/`restart` report and act on real service state: liveness falls back to `serve.pid` when `systemctl` is absent, and `restart` refuses on non-service modes before stopping.
|
|
19
|
+
- `upgrade` runs the new binary's `migrate` before the smoke check, restores the config on rollback, and emits `upgrade_start_failed` with a remedy when the new version installs but won't start.
|
|
20
|
+
- `json_tail` no longer lets a blank-line flood evict the terminal round-log record; `init` commits only its scaffold files.
|
|
21
|
+
|
|
22
|
+
### Notes
|
|
23
|
+
- New event kinds: `detector_error`, `round_supervisor_wedged`, `stale_index_lock_cleared`, `upgrade_start_failed`. `RestartPreventExitStatus` stays `78 75` — environmental failures (round exit 76) are retried inside serve rather than stopping it.
|
|
24
|
+
|
|
25
|
+
See `docs/migrations/0.2.md`.
|
|
26
|
+
|
|
27
|
+
## [0.2.11] - 2026-08-29
|
|
28
|
+
|
|
29
|
+
### Changed
|
|
30
|
+
- systemd `serve` unit now uses `Restart=on-failure` with `RestartPreventExitStatus=78 75`: a deliberate stop (sentinel / stop-file / max-rounds / SIGTERM) and a config give-up stay stopped, while a genuine crash still restarts. Re-render or hand-edit existing units.
|
|
31
|
+
- Throttle-aware skip is keyed on the **agent** (binary basename of `command[0]`), not the phase: every phase sharing a rate-limited agent is stepped over together, so a multi-provider rotation no longer hammers one throttled key while a healthy provider keeps running.
|
|
32
|
+
|
|
33
|
+
### Fixed
|
|
34
|
+
- `round` exits non-zero on a genuine crash, so the crash-loop breaker (`crash_loop`, exit 75) sees crashes instead of a masked exit 0; a permanent config failure gives up with exit 78 (`config_broken`) instead of restart-looping.
|
|
35
|
+
- Round deadlines and sleeps are measured on the monotonic clock — an NTP step no longer mis-fires or defers a hard-wall timeout.
|
|
36
|
+
- Back-off and restart sleeps are chunked, so a SIGTERM lands within one chunk instead of after a multi-hour throttle window; an interrupted back-off leaves the throttle active (no false recovered).
|
|
37
|
+
- A grace-killed round still dispatches its dirty work and is no longer miscounted as a timeout.
|
|
38
|
+
- Only one `serve` loop runs per project (loop-lifetime lock); `serve.pid` records a start-time token so `stop`/`kill` never signals a recycled PID.
|
|
39
|
+
|
|
40
|
+
### Notes
|
|
41
|
+
- `peek --json` schema `1.10`: `rate_limit.throttled_agents` lists all currently-throttled agents. Additive; no config change.
|
|
42
|
+
|
|
43
|
+
See `docs/migrations/0.2.md`.
|
|
44
|
+
|
|
8
45
|
## [0.2.10] - 2026-08-29
|
|
9
46
|
|
|
10
47
|
### 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.12
|
|
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
|
|
@@ -157,10 +157,15 @@ def render_event_kinds_list() -> str:
|
|
|
157
157
|
|
|
158
158
|
|
|
159
159
|
def _render_migrate_transforms() -> str:
|
|
160
|
-
"""Bullet list of the transforms `agent-runner migrate` applies, from the registry.
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
160
|
+
"""Bullet list of the transforms `agent-runner migrate` applies, from the registry.
|
|
161
|
+
A few entries carry a `parsed -> str` describe (so the manual report can name the
|
|
162
|
+
exact offending key found in a real config); rendered here with `{}`, which degrades
|
|
163
|
+
to the same generic instruction since there's no config in hand."""
|
|
164
|
+
from agent_runner.migrations import MIGRATIONS, _describe
|
|
165
|
+
|
|
166
|
+
# No config in hand here, so pass an empty parsed dict: a `parsed -> str`
|
|
167
|
+
# describe degrades to its generic instruction, same rule as the manual report.
|
|
168
|
+
return "\n".join(f"- {_describe(m, {})}" for m in MIGRATIONS)
|
|
164
169
|
|
|
165
170
|
|
|
166
171
|
def _subparser_action() -> argparse.Action:
|
|
@@ -27,9 +27,11 @@ __all__ = [
|
|
|
27
27
|
"emit_round_progress",
|
|
28
28
|
"emit_round_substrate_after",
|
|
29
29
|
"emit_round_substrate_before",
|
|
30
|
+
"emit_round_supervisor_wedged",
|
|
30
31
|
"emit_schedule_paused",
|
|
31
32
|
"emit_schedule_phase_skipped",
|
|
32
33
|
"emit_schedule_resumed",
|
|
34
|
+
"emit_stale_index_lock_cleared",
|
|
33
35
|
"emit_stop_file_detected",
|
|
34
36
|
"emit_transient_error_backoff_capped",
|
|
35
37
|
"emit_transient_error_detected",
|
|
@@ -98,6 +100,15 @@ def emit_stop_file_detected(
|
|
|
98
100
|
)
|
|
99
101
|
|
|
100
102
|
|
|
103
|
+
def emit_stale_index_lock_cleared(log_dir: Path, *, lock_path: str, round_num: int) -> None:
|
|
104
|
+
"""Emit when serve removed a .git/index.lock that its own timed-out+killed git
|
|
105
|
+
call orphaned. Single-writer: serve holds the round lock, so any lock surviving
|
|
106
|
+
our kill is ours to clear."""
|
|
107
|
+
from agent_runner.events import STALE_INDEX_LOCK_CLEARED, emit
|
|
108
|
+
|
|
109
|
+
emit(log_dir, STALE_INDEX_LOCK_CLEARED, lock_path=lock_path, round_num=round_num)
|
|
110
|
+
|
|
111
|
+
|
|
101
112
|
def emit_schedule_paused(
|
|
102
113
|
log_dir: Path, *, active_window: str, resume_at: str, timezone: str, phase: str = ""
|
|
103
114
|
) -> None:
|
|
@@ -168,6 +179,18 @@ def emit_round_substrate_after(
|
|
|
168
179
|
)
|
|
169
180
|
|
|
170
181
|
|
|
182
|
+
def emit_round_supervisor_wedged(
|
|
183
|
+
log_dir: Path, *, pid: int, timeout_s: int, log_path: Path
|
|
184
|
+
) -> None:
|
|
185
|
+
"""Emit when the round subprocess blew past the outer ceiling and serve had to
|
|
186
|
+
TERM/kill it (the round supervisor was wedged — not doing its own bounded
|
|
187
|
+
post-round cleanup). Distinct from round_timeout_kill (the AGENT hit the inner
|
|
188
|
+
wall inside a healthy round)."""
|
|
189
|
+
from agent_runner.events import ROUND_SUPERVISOR_WEDGED, emit
|
|
190
|
+
|
|
191
|
+
emit(log_dir, ROUND_SUPERVISOR_WEDGED, pid=pid, timeout_s=timeout_s, log_path=str(log_path))
|
|
192
|
+
|
|
193
|
+
|
|
171
194
|
def emit_fresh_eyes_round_triggered(log_dir: Path, *, round_num: int, every_n: int) -> None:
|
|
172
195
|
"""Emit fresh-eyes signal trigger event (only on triggered rounds)."""
|
|
173
196
|
from agent_runner.events import FRESH_EYES_ROUND_TRIGGERED, emit
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"""Pure serve restart policy — no I/O, no clock, no events read.
|
|
2
|
+
|
|
3
|
+
Extracted from api.py (0.2.12 Group G): serve_cmd imports the decision + exit
|
|
4
|
+
codes from here directly (see the architecture allowlist); api.py re-exports
|
|
5
|
+
them for external back-compat. Kept dependency-free so the serve loop stays a
|
|
6
|
+
thin dispatcher and the policy is unit-testable in isolation.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from typing import Literal
|
|
12
|
+
|
|
13
|
+
# Exit code for a permanent (no-retry) startup-battery failure. A broken config
|
|
14
|
+
# does not self-heal between rounds, so serve STOPS rather than respawning it
|
|
15
|
+
# forever. 78 = EX_CONFIG (sysexits) — avoids argparse's 2 and the generic 1.
|
|
16
|
+
PERMANENT_CONFIG_EXIT = 78
|
|
17
|
+
|
|
18
|
+
# Exit code serve returns when the crash-loop breaker trips (a give-up stop, like
|
|
19
|
+
# config_broken). Distinct from 78 so `systemctl status` / SuccessExitStatus can
|
|
20
|
+
# tell the two "needs intervention" stops apart. 75 = EX_TEMPFAIL (sysexits).
|
|
21
|
+
# The systemd unit lists both in RestartPreventExitStatus so a deliberate stop
|
|
22
|
+
# stays stopped (and visibly failed) while an unexpected supervisor crash restarts.
|
|
23
|
+
CRASH_LOOP_EXIT = 75
|
|
24
|
+
|
|
25
|
+
# Exit code for an ENVIRONMENTAL startup-battery failure (ENOSPC, mount hiccup,
|
|
26
|
+
# an unclassified check): recoverable, unlike a permanent config break. NOT in
|
|
27
|
+
# the unit's RestartPreventExitStatus (stays "78 75") so 76 restarts; treated
|
|
28
|
+
# exactly like an active throttle (post_round_decision), so serve keeps
|
|
29
|
+
# retrying at a fixed doubled delay with the crash-loop breaker disarmed,
|
|
30
|
+
# staying alive until the environment heals. StartLimit bounds only repeated
|
|
31
|
+
# serve-PROCESS death, not this round-level path. 76 = EX_PROTOCOL (sysexits).
|
|
32
|
+
ENV_BATTERY_EXIT = 76
|
|
33
|
+
|
|
34
|
+
# Crash-loop circuit breaker (b12). The serve loop escalates the restart delay
|
|
35
|
+
# on consecutive UNKNOWN short crashes (non-zero exit, short duration, no
|
|
36
|
+
# classified transient) and STOPS after CRASH_LOOP_THRESHOLD of them — the Run 6
|
|
37
|
+
# ~100-empty-rounds scar. Recoverable-slow failures (rate limit / 5h quota / 5xx
|
|
38
|
+
# / timeout) are already handled by the transient-error throttle and never reach
|
|
39
|
+
# this path. A clean (exit 0), long, or classified-transient round resets the run.
|
|
40
|
+
CRASH_LOOP_THRESHOLD = 5
|
|
41
|
+
CRASH_LOOP_SHORT_EXIT_S = 60 # mirrors monitor.SHORT_EXIT_THRESHOLD_S
|
|
42
|
+
CRASH_LOOP_MAX_DELAY_S = 1800 # cap the escalating restart delay (30 min)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
# The action strings below are the restart-action enum, not events.py kinds:
|
|
46
|
+
# "continue" has no constant, and a constant cannot sit inside Literal[...].
|
|
47
|
+
def post_round_decision(
|
|
48
|
+
*,
|
|
49
|
+
returncode: int,
|
|
50
|
+
duration_s: float,
|
|
51
|
+
throttle_active: bool,
|
|
52
|
+
consecutive: int,
|
|
53
|
+
restart_delay_s: int,
|
|
54
|
+
) -> tuple[Literal["config_broken", "crash_loop", "continue"], int, int]:
|
|
55
|
+
"""Restart policy after one round — keeps the serve loop a thin dispatcher.
|
|
56
|
+
|
|
57
|
+
Returns ``(action, delay_s, consecutive)`` where action is:
|
|
58
|
+
- ``"config_broken"`` — permanent startup failure (b18): stop.
|
|
59
|
+
- ``"crash_loop"`` — CRASH_LOOP_THRESHOLD consecutive unknown short crashes
|
|
60
|
+
(b12): stop. An unknown short crash is a non-zero, fast exit with no
|
|
61
|
+
classified transient (rate-limit/5xx/timeout are handled by the throttle).
|
|
62
|
+
- ``"continue"`` — sleep ``delay_s`` then run the next round.
|
|
63
|
+
|
|
64
|
+
A clean (exit 0), long, or transient round resets ``consecutive`` to 0; an
|
|
65
|
+
unknown short crash escalates the delay (restart × 2ⁿ, capped) until the stop.
|
|
66
|
+
An ``ENV_BATTERY_EXIT`` (76, environmental startup-battery failure) is treated
|
|
67
|
+
exactly like an active throttle: it takes the flat ``restart_delay_s * 2``
|
|
68
|
+
delay below (never escalating) and resets ``consecutive`` to 0, so it never
|
|
69
|
+
counts toward the crash-loop breaker — a short environmental outage (ENOSPC,
|
|
70
|
+
mount hiccup) never trips ``crash_loop``. This always returns ``"continue"``,
|
|
71
|
+
so serve itself never exits 76 and systemd's StartLimit window never engages
|
|
72
|
+
for this path; a *persistent* environmental failure keeps serve alive
|
|
73
|
+
retrying at the doubled delay until the environment heals. StartLimit bounds
|
|
74
|
+
only repeated serve-PROCESS death, independent of this round-level path.
|
|
75
|
+
"""
|
|
76
|
+
if returncode == PERMANENT_CONFIG_EXIT:
|
|
77
|
+
return ("config_broken", 0, consecutive)
|
|
78
|
+
throttle_active = throttle_active or returncode == ENV_BATTERY_EXIT
|
|
79
|
+
unknown_short_crash = (
|
|
80
|
+
returncode != 0 and duration_s < CRASH_LOOP_SHORT_EXIT_S and not throttle_active
|
|
81
|
+
)
|
|
82
|
+
if unknown_short_crash:
|
|
83
|
+
consecutive += 1
|
|
84
|
+
if consecutive >= CRASH_LOOP_THRESHOLD:
|
|
85
|
+
return ("crash_loop", 0, consecutive)
|
|
86
|
+
delay = min(restart_delay_s * 2**consecutive, CRASH_LOOP_MAX_DELAY_S)
|
|
87
|
+
return ("continue", delay, consecutive)
|
|
88
|
+
delay = restart_delay_s if returncode == 0 else restart_delay_s * 2
|
|
89
|
+
return ("continue", delay, 0)
|