cli-agent-runner 0.3.7__tar.gz → 0.3.9__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/.vulture-whitelist.py +1 -30
- cli_agent_runner-0.3.9/BACKLOG.md +43 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/CHANGELOG.md +20 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/CONTRIBUTING.md +5 -4
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/PKG-INFO +5 -6
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/README.md +4 -2
- cli_agent_runner-0.3.9/agent_runner/__init__.py +121 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/_docgen.py +4 -3
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/_emit/__init__.py +0 -14
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/_emit/memory.py +9 -1
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/_monitor_registry.py +2 -17
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/_monitor_state.py +19 -19
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/_notify.py +3 -8
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/_observe.py +1 -6
- cli_agent_runner-0.3.9/agent_runner/_plugin_manifest.py +181 -0
- cli_agent_runner-0.3.9/agent_runner/_registry.py +38 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/_throttle.py +6 -5
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/_version.py +2 -2
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/agent_runtime.py +39 -7
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/api.py +0 -6
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/api_types.py +3 -36
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/builtin_plugins/claude_rate_limit.py +16 -1
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/builtin_plugins/gemini.py +1 -1
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/builtin_plugins/pi.py +3 -1
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/cli/_serve_round.py +4 -189
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/cli/common.py +10 -14
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/cli/doctor_cmd.py +9 -25
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/cli/events_cmd.py +50 -121
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/cli/monitor_cmd.py +2 -2
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/cli/peek_cmd.py +2 -2
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/cli/serve_cmd.py +49 -64
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/config/__init__.py +1 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/config/models.py +25 -26
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/config/parsers.py +13 -81
- cli_agent_runner-0.3.9/agent_runner/event_log.py +198 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/events.py +8 -94
- cli_agent_runner-0.3.9/agent_runner/hooks.py +139 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/host_health.py +6 -3
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/http_progress.py +8 -10
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/migrations.py +212 -100
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/monitor.py +11 -43
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/presets/claude.toml +3 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/runner.py +33 -117
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/vcs_state.py +138 -174
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/docs/architecture.md +39 -62
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/docs/commands.md +20 -9
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/docs/configuration.md +68 -26
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/docs/events.md +3 -3
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/docs/long-running-agents.md +4 -4
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/docs/memory-efficiency.md +95 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/docs/migrations/0.3.md +32 -6
- cli_agent_runner-0.3.9/docs/plugins.md +374 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/docs/recipes/pi.md +8 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/docs/runbook.md +32 -45
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/docs/thesis.md +9 -9
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/pyproject.toml +9 -13
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/_clock.py +6 -1
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/_test_helpers.py +9 -89
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/conftest.py +2 -17
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/contract/test_public_api_surface.py +0 -50
- cli_agent_runner-0.3.9/tests/integration/test_cooperative_stop_signal.py +126 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/integration/test_run_one_round_with_fake_agent.py +27 -7
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/_event_scan.py +1 -1
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_architecture.py +2 -10
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_doc_builtin_plugins.py +1 -2
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_doc_claims_match_ssot.py +5 -6
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_doc_cli_claims.py +0 -16
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_doc_operator_surface.py +1 -36
- cli_agent_runner-0.3.9/tests/invariants/test_event_kind_registry.py +33 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_event_kinds_ssot.py +1 -1
- cli_agent_runner-0.3.9/tests/invariants/test_hard_wall_signal.py +126 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_hook_contract_docs.py +2 -2
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_import_footprint.py +8 -11
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_layer_2_loop_size.py +1 -1
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_module_boundaries.py +0 -1
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_peek_schema_version.py +3 -20
- cli_agent_runner-0.3.9/tests/invariants/test_plugins_config_stable.py +38 -0
- cli_agent_runner-0.3.9/tests/invariants/test_throttle_stateless_imports.py +40 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_timeout_budget_invariant.py +1 -12
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_api_observation.py +8 -9
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_api_resolve_phase.py +1 -10
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_apply_reap_grace_env.py +3 -3
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_config.py +23 -44
- cli_agent_runner-0.3.9/tests/unit/test_cooperative_signal_env.py +101 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_detect_hung_latch.py +9 -11
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_docgen.py +0 -1
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_doctor_cmd.py +0 -55
- cli_agent_runner-0.3.9/tests/unit/test_event_log.py +174 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_events.py +4 -113
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_events_cmd.py +2 -1
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_events_cmd_rollover.py +16 -11
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_events_cmd_tail.py +81 -1
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_hooks.py +1 -76
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_init_entry_points.py +21 -52
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_migrate_cmd.py +32 -3
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_migrations.py +97 -8
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_peek_select.py +1 -1
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_phase_agent_launch.py +4 -4
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_plugin_constants.py +18 -0
- cli_agent_runner-0.3.9/tests/unit/test_plugin_manifest.py +259 -0
- cli_agent_runner-0.3.9/tests/unit/test_plugins_config_fields.py +23 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_presets.py +15 -0
- cli_agent_runner-0.3.7/tests/unit/test_default_dirty_handler.py → cli_agent_runner-0.3.9/tests/unit/test_resolve_dirty_tree.py +30 -35
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_runner.py +6 -223
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_serve_round_oom_killed.py +21 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_vcs_state.py +0 -82
- cli_agent_runner-0.3.7/BACKLOG.md +0 -98
- cli_agent_runner-0.3.7/agent_runner/__init__.py +0 -224
- cli_agent_runner-0.3.7/agent_runner/_emit/plugins.py +0 -76
- cli_agent_runner-0.3.7/agent_runner/_plugin_checksum.py +0 -62
- cli_agent_runner-0.3.7/agent_runner/_plugin_manifest.py +0 -191
- cli_agent_runner-0.3.7/agent_runner/_plugin_sandbox.py +0 -615
- cli_agent_runner-0.3.7/agent_runner/_registry.py +0 -69
- cli_agent_runner-0.3.7/agent_runner/_sandbox_probe.py +0 -326
- cli_agent_runner-0.3.7/agent_runner/builtin_plugins/default_dirty_handler.py +0 -92
- cli_agent_runner-0.3.7/agent_runner/hooks.py +0 -463
- cli_agent_runner-0.3.7/docs/plugins.md +0 -728
- cli_agent_runner-0.3.7/tests/integration/test_context_enricher_namespacing.py +0 -57
- cli_agent_runner-0.3.7/tests/integration/test_dirty_handler_seam.py +0 -97
- cli_agent_runner-0.3.7/tests/integration/test_plugin_detector_loaded.py +0 -100
- cli_agent_runner-0.3.7/tests/integration/test_plugin_owned_paths.py +0 -284
- cli_agent_runner-0.3.7/tests/invariants/test_builtin_plugin_names_sync.py +0 -21
- cli_agent_runner-0.3.7/tests/invariants/test_event_kind_registry.py +0 -70
- cli_agent_runner-0.3.7/tests/invariants/test_kill_tests_not_skipped.py +0 -20
- cli_agent_runner-0.3.7/tests/invariants/test_plugins_config_stable.py +0 -40
- cli_agent_runner-0.3.7/tests/linux/test_plugin_sandbox_kill.py +0 -149
- cli_agent_runner-0.3.7/tests/unit/test_builtin_provenance.py +0 -31
- cli_agent_runner-0.3.7/tests/unit/test_collapse_spawn_decisions.py +0 -33
- cli_agent_runner-0.3.7/tests/unit/test_detector_protocol.py +0 -64
- cli_agent_runner-0.3.7/tests/unit/test_dirty_handlers.py +0 -60
- cli_agent_runner-0.3.7/tests/unit/test_dispatch_dirty_owner_branch.py +0 -261
- cli_agent_runner-0.3.7/tests/unit/test_doctor_sandbox.py +0 -75
- cli_agent_runner-0.3.7/tests/unit/test_example_dirty_handler.py +0 -49
- cli_agent_runner-0.3.7/tests/unit/test_gate_serve_boot.py +0 -90
- cli_agent_runner-0.3.7/tests/unit/test_hook_failure_isolation.py +0 -69
- cli_agent_runner-0.3.7/tests/unit/test_load_fail_closed.py +0 -165
- cli_agent_runner-0.3.7/tests/unit/test_manifest_spawn_hooks.py +0 -66
- cli_agent_runner-0.3.7/tests/unit/test_peek_sandbox_block.py +0 -154
- cli_agent_runner-0.3.7/tests/unit/test_plugin_checksum.py +0 -44
- cli_agent_runner-0.3.7/tests/unit/test_plugin_manifest.py +0 -177
- cli_agent_runner-0.3.7/tests/unit/test_plugin_name_mismatch.py +0 -71
- cli_agent_runner-0.3.7/tests/unit/test_plugin_sandbox_wire.py +0 -564
- cli_agent_runner-0.3.7/tests/unit/test_plugins_config_fields.py +0 -59
- cli_agent_runner-0.3.7/tests/unit/test_primary_prompt_file_home.py +0 -29
- cli_agent_runner-0.3.7/tests/unit/test_sandbox_probe.py +0 -74
- cli_agent_runner-0.3.7/tests/unit/test_serve_startup_hooks.py +0 -206
- cli_agent_runner-0.3.7/tests/unit/test_spawn_seam.py +0 -457
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/.codecov.yml +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/.github/dependabot.yml +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/.github/workflows/ci.yml +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/.github/workflows/release.yml +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/.gitignore +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/CODE_OF_CONDUCT.md +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/LICENSE +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/README.zh.md +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/SECURITY.md +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/_emit/agent.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/_emit/rounds.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/_emit/serve.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/_install.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/_lifecycle.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/_monitor_detectors.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/_plugin_scan.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/_procwait.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/_redact.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/_resolve.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/_round_outcome.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/_round_support.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/_serve_policy.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/_substrate.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/builtin_plugins/__init__.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/builtin_plugins/_constants.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/builtin_plugins/codewhale.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/builtin_plugins/kimi.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/cli/__init__.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/cli/__main__.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/cli/_serve_cgroup.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/cli/init_cmd.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/cli/install_cmd.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/cli/migrate_cmd.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/cli/round_cmd.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/cli/service_cmd.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/cli/upgrade_cmd.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/clock.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/config/errors.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/config/loader.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/config/validators.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/context_store.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/defenses.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/lifecycle.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/metrics.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/phase_select.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/presets/__init__.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/presets/aider.toml +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/presets/codewhale.toml +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/presets/gemini.toml +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/presets/kimi.toml +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/presets/pi.toml +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/prompt_loader.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/remote_relay.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/round_log.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/round_view.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/scaffold.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/schedule.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/service_unit.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/agent_runner/startup_check.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/build.sh +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/deploy/Dockerfile +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/deploy/docker-compose.yml +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/docs/README.md +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/docs/migrations/0.2.md +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/docs/quickstart.md +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/docs/recipes/aider.md +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/docs/recipes/codewhale.md +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/docs/recipes/container-pi.md +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/docs/recipes/deploy-all-in-one.md +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/docs/recipes/kimi.md +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/__init__.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/contract/__init__.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/e2e/__init__.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/e2e/conftest.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/e2e/test_e2e_graceful_stop.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/e2e/test_e2e_install_systemd.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/e2e/test_e2e_monitor_remote.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/e2e/test_e2e_round_lifecycle.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/fixtures/cli-real-output/claude-2.1.143-assistant-tool-use.jsonl +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/fixtures/cli-real-output/claude-2.1.143-result-event.jsonl +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/fixtures/cli-real-output/gemini-0.42.0-result-event.jsonl +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/generate_vulture_whitelist.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/integration/__init__.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/integration/test_auto_stop_e2e.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/integration/test_bounded_run.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/integration/test_cooperative_grace_property.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/integration/test_fresh_eyes_signal.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/integration/test_grace_kill_emission.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/integration/test_install_dry_run.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/integration/test_monitor_seeded.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/integration/test_plugin_real_flow.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/integration/test_prompt_delivery_stdin.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/integration/test_reap_property.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/integration/test_scaffold_presets.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/integration/test_serve_loop.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/integration/test_spawn_round_mem_floor.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/integration/test_spawn_round_wedged.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/integration/test_substrate_fingerprint.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/integration/test_transient_error_backoff.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/__init__.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/_docs.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_atomic_write_enforced.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_authored_facts_declared.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_auto_stop_policy_ssot.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_bdd_test_conventions.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_brake_defaults_off.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_catalogs.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_classification_ssot.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_config_error_consistency.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_config_value_set_ssot.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_container_stop_bound.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_dataclass_fields_have_producers.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_doc_test_pointers_exist.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_doc_transient_error_claims.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_doc_usage_event_fields.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_docs_generated.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_docs_index_complete.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_entry_points_resolve.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_event_int_coercion.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_events_doc_contract.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_gen_blocks_name_their_source.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_migrations_registry_ssot.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_module_sizes.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_monitor_self_exclusion.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_no_ai_signatures.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_no_asyncio_select.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_no_direct_inspect_import.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_no_internal_refs.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_no_price_logic.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_no_pytest_skip_on_parse_fail.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_no_raw_time.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_no_vacuous_invariants.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_no_version_refs.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_phase_select_stateless.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_procwait_shield.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_readme_zh_is_pointer.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_repo_constants_patched_in_tests.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_round_alloc_growth.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_round_log_decode_boundary.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_round_num_single_source.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_round_result_stable.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_set_diff_for_auto_tool_classification.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_stash_uses_sha_not_index.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_upstream_schema_canary.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/invariants/test_vulture_whitelist_generated.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/linux/__init__.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/linux/test_memory_high_nudge_e2e.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/literate/__init__.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/literate/parser.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/literate/test_parser.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/literate/test_quickstart.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/__init__.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_agent_runtime.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_agent_runtime_container.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_agent_runtime_grace.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_agent_runtime_marker_scan.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_agent_runtime_progress.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_agent_runtime_reap.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_agent_runtime_signal_name.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_api_assemble_prompt.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_api_events_stream.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_api_install.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_api_read_round_num.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_api_service.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_api_types.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_auto_stop_gating.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_catalogs.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_cgroup_probe.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_claude_error_detector.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_claude_foreign_schema.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_cli.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_cli_common.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_cli_init_install.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_cli_main_boundary.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_cli_monitor_http.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_cli_service_peek_monitor.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_cli_upgrade.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_codewhale_code_precedence.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_codewhale_plugin.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_coerce_int_poison.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_config_fresh_eyes.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_config_max_rounds.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_config_nested_strictness.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_config_prompt_delivery.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_config_schedule.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_config_stop_file.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_config_strictness.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_config_substrate_fingerprint_paths.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_config_transient_error_action.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_context_store.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_control_char_config.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_defenses.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_detector_isolation.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_effective_throttle_view.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_emit_config_migrated.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_emit_schedule.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_emit_schedule_phase_skipped.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_events_jsonl_decode.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_example_plugin.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_exec_prefix.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_exit_cause.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_exit_classifier.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_fresh_eyes_trigger.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_gemini_plugin.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_git_timeout.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_hook_redact_order.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_host_health.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_http_progress.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_http_progress_epoch.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_interruptible_sleep_should_stop.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_kill_pgroup_shielding.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_kimi_plugin.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_lifecycle.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_loader_split.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_metrics.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_metrics_cgroup_usage.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_metrics_swap.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_monitor_assembly.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_monitor_cmd_severity.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_monitor_dedup_identity.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_monitor_dedup_rearm.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_monitor_detect_anomaly_repetitive.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_monitor_detect_rate_limit.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_monitor_detect_supervisor_stale.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_monitor_detectors.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_monitor_event_tail.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_monitor_loop.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_monitor_on_alert.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_monitor_remote.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_monitor_round_deferred_stale.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_monitor_schedule_pause.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_network_blip_signal_guard.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_notify.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_open_round_log.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_orphan_chain_single_pass.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_outer_round_ceiling.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_peek_argparse.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_peek_project_isolation.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_peek_schedule.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_phase_profiles.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_phase_select.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_pi_plugin.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_plugin_scan_parity.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_procwait.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_prompt_loader.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_read_json_hardening.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_redact.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_resolve.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_round_cmd.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_round_cmd_sigterm.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_round_log_helpers.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_round_outcome.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_round_outcome_agent_axis.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_round_view.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_runner_sidecar_ordering.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_runner_throttle.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_scaffold.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_schedule.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_serve_cmd_bounded.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_serve_config_broken.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_serve_crash_loop.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_serve_mem_gate.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_serve_phase_schedule.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_serve_policy.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_serve_round.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_serve_round_cgroup_spine.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_serve_round_log.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_serve_round_terminate.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_serve_round_wait_exit.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_serve_schedule_gate.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_serve_sentinel.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_serve_wakeup.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_service_mode.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_service_unit.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_startup_battery_exit.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_startup_check.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_substrate.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_supervisor_stale_self_blind.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_terminate_round_wait_exit.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_throttle_back_off_ladder.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_throttle_epoch_bound.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_throttle_plugin_classification.py +0 -0
- {cli_agent_runner-0.3.7 → cli_agent_runner-0.3.9}/tests/unit/test_upgrade_migrate.py +0 -0
|
@@ -15,15 +15,8 @@ buffer
|
|
|
15
15
|
|
|
16
16
|
# agent_runner._plugin_manifest.PluginManifest
|
|
17
17
|
name
|
|
18
|
-
pre_round_hooks
|
|
19
|
-
context_enrichers
|
|
20
18
|
post_round_hooks
|
|
21
|
-
|
|
22
|
-
dirty_handlers
|
|
23
|
-
spawn_hooks
|
|
24
|
-
detectors
|
|
25
|
-
event_kinds
|
|
26
|
-
sigterm_cooperative
|
|
19
|
+
cooperative_stop
|
|
27
20
|
|
|
28
21
|
# agent_runner._round_outcome.RoundOutcome
|
|
29
22
|
mem_terminated
|
|
@@ -36,12 +29,6 @@ usage_capable_by_agent
|
|
|
36
29
|
newest_usage_ts_by_agent
|
|
37
30
|
backoff_exponent_by_agent
|
|
38
31
|
|
|
39
|
-
# agent_runner._sandbox_probe.SandboxProbe
|
|
40
|
-
achieved_tier
|
|
41
|
-
landlock_abi
|
|
42
|
-
seccomp
|
|
43
|
-
unconfined_reason
|
|
44
|
-
|
|
45
32
|
# agent_runner.agent_runtime.RunResult
|
|
46
33
|
exit_code
|
|
47
34
|
duration_s
|
|
@@ -131,11 +118,6 @@ unit_file
|
|
|
131
118
|
rate_limit
|
|
132
119
|
system_managed
|
|
133
120
|
|
|
134
|
-
# agent_runner.api_types.SpawnDecision
|
|
135
|
-
action
|
|
136
|
-
defer_s
|
|
137
|
-
reason
|
|
138
|
-
|
|
139
121
|
# agent_runner.api_types.SystemMetrics
|
|
140
122
|
mem_total_mb
|
|
141
123
|
mem_available_mb
|
|
@@ -156,7 +138,6 @@ phase
|
|
|
156
138
|
checks
|
|
157
139
|
overlaps
|
|
158
140
|
plan
|
|
159
|
-
sandbox
|
|
160
141
|
cgroup
|
|
161
142
|
sigterm_grace
|
|
162
143
|
|
|
@@ -199,7 +180,6 @@ brake
|
|
|
199
180
|
|
|
200
181
|
# agent_runner.config.models.PhaseOverride
|
|
201
182
|
round_budget_s
|
|
202
|
-
disable_pre_round_hooks
|
|
203
183
|
prompt_files
|
|
204
184
|
agent
|
|
205
185
|
schedule
|
|
@@ -211,10 +191,6 @@ phase_policy
|
|
|
211
191
|
|
|
212
192
|
# agent_runner.config.models.PluginsConfig
|
|
213
193
|
disable
|
|
214
|
-
spawn_override_allow
|
|
215
|
-
sandbox
|
|
216
|
-
pin
|
|
217
|
-
raw
|
|
218
194
|
|
|
219
195
|
# agent_runner.config.models.Profile
|
|
220
196
|
agent
|
|
@@ -235,7 +211,6 @@ work_dir
|
|
|
235
211
|
log_dir
|
|
236
212
|
round_budget_s
|
|
237
213
|
restart_delay_s
|
|
238
|
-
disable_pre_round_hooks
|
|
239
214
|
round_log_retention
|
|
240
215
|
narrative_file
|
|
241
216
|
transient_error_action
|
|
@@ -316,10 +291,6 @@ anomaly_repetitive_window
|
|
|
316
291
|
anomaly_repetitive_threshold
|
|
317
292
|
vcs
|
|
318
293
|
|
|
319
|
-
# agent_runner.hooks.SpawnView
|
|
320
|
-
argv
|
|
321
|
-
env
|
|
322
|
-
|
|
323
294
|
# agent_runner.hooks.VcsHookView
|
|
324
295
|
dirty_action
|
|
325
296
|
stash_idempotency_s
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Backlog
|
|
2
|
+
|
|
3
|
+
Known follow-ups that are real design or behavior decisions, not defects. Each
|
|
4
|
+
entry carries enough context to act on without re-deriving it.
|
|
5
|
+
|
|
6
|
+
Items marked **NEEDS_DESIGN** change user-visible behavior and are held for an
|
|
7
|
+
explicit decision — they are not shipped silently in a maintenance release.
|
|
8
|
+
|
|
9
|
+
**Ordered by priority** (highest first). The number is a rank, not a stable id.
|
|
10
|
+
|
|
11
|
+
## 1. `_tail_events` / `_tail_events_jsonl` duplication
|
|
12
|
+
|
|
13
|
+
Three event-stream tailers now exist at deliberately different scopes, and they
|
|
14
|
+
are not accidental copies:
|
|
15
|
+
|
|
16
|
+
- `cli/events_cmd.py:_tail_events` — current-month-scoped
|
|
17
|
+
(`_current_month_events_file`), resets its offset to `0` on truncation.
|
|
18
|
+
- `_monitor_state.py:_tail_events_jsonl` — globs every `events-*.jsonl`;
|
|
19
|
+
re-exported through the `monitor.py` facade. It moved out of `api.py` in the
|
|
20
|
+
0.3.0 api split (`_install`/`_lifecycle`/`_observe`).
|
|
21
|
+
- `_throttle.py:_tail_events` — the newest two monthly files
|
|
22
|
+
(`glob("events-*.jsonl")[-2:]`).
|
|
23
|
+
|
|
24
|
+
Collapsing them means first deciding which scope is correct for each caller — a
|
|
25
|
+
structural decision, not a literal swap. (The older "character-identical
|
|
26
|
+
kind-read loop in `_throttle.py` and `monitor.py`" sub-concern has evaporated:
|
|
27
|
+
`monitor.py` no longer carries that loop — it moved to `_monitor_detectors.py`
|
|
28
|
+
and grew its own reset-ladder logic — and `_throttle.py` iterates forward over
|
|
29
|
+
the tailer generator, so the only shared text left is the single line
|
|
30
|
+
`kind = ev.get("event")`.)
|
|
31
|
+
|
|
32
|
+
## 2. `stash_orphan` loses the ref when the post-push listing fails
|
|
33
|
+
|
|
34
|
+
`vcs_state.stash_orphan` returns `None` in three cases; two are true no-ops. The
|
|
35
|
+
third — `git stash push` succeeded but the follow-up `git stash list` failed —
|
|
36
|
+
means the WIP *is* stashed yet callers read "nothing stashed" and report the
|
|
37
|
+
tree as ignored. It is already documented in-code as a KNOWN GAP and judged
|
|
38
|
+
effectively unreachable (a listing that fails microseconds after a push that
|
|
39
|
+
just succeeded in the same repo).
|
|
40
|
+
|
|
41
|
+
Deferred because closing it is a naming decision, not cleanup: no event kind
|
|
42
|
+
carries the meaning "stashed but ref lost" (`orphan_stash_failed` would be wrong
|
|
43
|
+
— the stash exists). Left as-is until that kind is designed.
|
|
@@ -5,6 +5,26 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.3.9] - 2026-09-17
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
- `PluginManifest` narrows to 3 fields (`name`, `post_round_hooks`, `cooperative_stop`) — dropped 6 zero-producer hook seams, the `DirtyHandler` seam (dirty-tree resolution is now plain core), the sandbox subsystem, and the owned-paths registry, all with zero real producers.
|
|
12
|
+
- `sigterm_cooperative: bool` is now typed `cooperative_stop: Literal["SIGTERM", "SIGINT"] | None`: `claude` now drains on SIGINT (SIGTERM abandoned its turn), `gemini`/`pi` stay on SIGTERM; the hard-wall kill path stays SIGTERM-first regardless.
|
|
13
|
+
- The `claude` builtin plugin's manifest/entry-point name changed from `claude_rate_limit` to `claude` (`agent-runner migrate` flags any `[plugins] disable` entry still naming the old value).
|
|
14
|
+
- `peek --json` schema bumps to `2.6`.
|
|
15
|
+
|
|
16
|
+
### Removed
|
|
17
|
+
- `[plugins]` `sandbox`/`pin`/`spawn_override_allow`/`raw` config keys and `[runtime]`/`[phases.<name>]` `disable_pre_round_hooks` — run `agent-runner migrate` before upgrading.
|
|
18
|
+
|
|
19
|
+
## [0.3.8] - 2026-09-16
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
- `try_auto_commit` (`vcs.dirty_action = "auto_commit"`) now honors the plugin-owned-paths registry, matching `stash_orphan`: paths registered via `register_plugin_owned_paths` are excluded from the auto-commit, so a plugin's deliverables no longer land in the agent's git history.
|
|
23
|
+
- `round_oom_killed` now also carries `events_oom_kill_delta` — the canonical name, sibling-consistent with `round_cgroup_memory`'s counters; the original bare `oom_kill_delta` is retained as an alias (a future breaking release drops it).
|
|
24
|
+
|
|
25
|
+
### Added
|
|
26
|
+
- The `claude` preset arms the repetitive-tool-call anomaly detector (`[monitor] anomaly_repetitive_window = 30`, `anomaly_repetitive_threshold = 15`) — trips only on an egregious stuck loop (the same tool+target ≥15× within 30 calls). The global default stays opt-in (disabled).
|
|
27
|
+
|
|
8
28
|
## [0.3.7] - 2026-09-15
|
|
9
29
|
|
|
10
30
|
### Added
|
|
@@ -75,10 +75,11 @@ into `docs/commands.md` from the registry) plus `CHANGELOG.md`. Between them
|
|
|
75
75
|
they carry a config rewrite and per-version notes; a doc that only restates the
|
|
76
76
|
changelog is upkeep with no reader.
|
|
77
77
|
|
|
78
|
-
`docs/migrations/0.2.md`
|
|
79
|
-
steps a config rewrite can't do (recovery
|
|
80
|
-
|
|
81
|
-
|
|
78
|
+
`docs/migrations/0.2.md` and `docs/migrations/0.3.md` are the two surviving
|
|
79
|
+
guides: they collect the few manual steps a config rewrite can't do (recovery
|
|
80
|
+
procedures, a systemd regen, a mode switch, the 0.3.0 breaking-release port).
|
|
81
|
+
Keep the relevant CHANGELOG entries terse and link the matching one
|
|
82
|
+
(`See docs/migrations/0.3.md.`).
|
|
82
83
|
|
|
83
84
|
Migration guides are **not** append-only. A per-version guide is pruned once its
|
|
84
85
|
content becomes executable (`migrate`), generated (the transform list),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: cli-agent-runner
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.9
|
|
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
|
|
@@ -34,9 +34,6 @@ Requires-Dist: ruff<0.17,>=0.16; extra == 'dev'
|
|
|
34
34
|
Requires-Dist: vulture>=2.13; extra == 'dev'
|
|
35
35
|
Provides-Extra: e2e
|
|
36
36
|
Requires-Dist: pytest>=8; extra == 'e2e'
|
|
37
|
-
Provides-Extra: sandbox
|
|
38
|
-
Requires-Dist: py-landlock==0.1.1; (sys_platform == 'linux') and extra == 'sandbox'
|
|
39
|
-
Requires-Dist: pyseccomp==0.1.2; (sys_platform == 'linux') and extra == 'sandbox'
|
|
40
37
|
Description-Content-Type: text/markdown
|
|
41
38
|
|
|
42
39
|
> **[中文](README.zh.md)** · English
|
|
@@ -93,7 +90,7 @@ Full walkthrough: [`docs/quickstart.md`](docs/quickstart.md).
|
|
|
93
90
|
| `start` / `stop` / `kill` | `watch` — peek in a refresh loop |
|
|
94
91
|
| `restart` / `status` | `monitor` — 13 detectors, alerts, auto-stop |
|
|
95
92
|
| `round` / `serve` | `events` — query / stream events.jsonl |
|
|
96
|
-
| `upgrade` / `migrate` | |
|
|
93
|
+
| `upgrade` / `migrate` | `doctor` — read-only pre-flight |
|
|
97
94
|
|
|
98
95
|
Verb reference: [`docs/commands.md`](docs/commands.md).
|
|
99
96
|
|
|
@@ -123,7 +120,9 @@ Notify only: `timeout_rate`, `hung`, `orphan_chain`, `disk_warning`,
|
|
|
123
120
|
`network_fail`, `rate_limit_active`, `anomaly_repetitive_active`,
|
|
124
121
|
`supervisor_stale`. `mem_pressure` also drives a separate serve-loop
|
|
125
122
|
admission gate that defers or terminates rounds under real memory pressure —
|
|
126
|
-
see `docs/architecture.md`.
|
|
123
|
+
see `docs/architecture.md`. An opt-in soft-brake (`[monitor.host_health.brake]`,
|
|
124
|
+
default off) can additionally cap the serve leaf's `memory.high` under sustained
|
|
125
|
+
pressure on a delegated cgroup.
|
|
127
126
|
|
|
128
127
|
**Auto-stop the service** (continuing is harmful):
|
|
129
128
|
- `oauth_fail` — burning API quota on auth-rejected rounds
|
|
@@ -52,7 +52,7 @@ Full walkthrough: [`docs/quickstart.md`](docs/quickstart.md).
|
|
|
52
52
|
| `start` / `stop` / `kill` | `watch` — peek in a refresh loop |
|
|
53
53
|
| `restart` / `status` | `monitor` — 13 detectors, alerts, auto-stop |
|
|
54
54
|
| `round` / `serve` | `events` — query / stream events.jsonl |
|
|
55
|
-
| `upgrade` / `migrate` | |
|
|
55
|
+
| `upgrade` / `migrate` | `doctor` — read-only pre-flight |
|
|
56
56
|
|
|
57
57
|
Verb reference: [`docs/commands.md`](docs/commands.md).
|
|
58
58
|
|
|
@@ -82,7 +82,9 @@ Notify only: `timeout_rate`, `hung`, `orphan_chain`, `disk_warning`,
|
|
|
82
82
|
`network_fail`, `rate_limit_active`, `anomaly_repetitive_active`,
|
|
83
83
|
`supervisor_stale`. `mem_pressure` also drives a separate serve-loop
|
|
84
84
|
admission gate that defers or terminates rounds under real memory pressure —
|
|
85
|
-
see `docs/architecture.md`.
|
|
85
|
+
see `docs/architecture.md`. An opt-in soft-brake (`[monitor.host_health.brake]`,
|
|
86
|
+
default off) can additionally cap the serve leaf's `memory.high` under sustained
|
|
87
|
+
pressure on a delegated cgroup.
|
|
86
88
|
|
|
87
89
|
**Auto-stop the service** (continuing is harmful):
|
|
88
90
|
- `oauth_fail` — burning API quota on auth-rejected rounds
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"""Agent Runner — restart-on-exit supervisor for autonomous CLI agents."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
try:
|
|
6
|
+
from agent_runner._version import __version__
|
|
7
|
+
except ImportError: # editable install before hatch-vcs has generated _version.py
|
|
8
|
+
__version__ = "0.0.0+unknown"
|
|
9
|
+
|
|
10
|
+
_PLUGIN_GROUP = "agent_runner.plugins"
|
|
11
|
+
|
|
12
|
+
# Tracks the names passed to the most recent ``apply_plugin_disable`` call.
|
|
13
|
+
# Surfaced via peek --json `plugins.disabled` for operator visibility.
|
|
14
|
+
_DISABLED_PLUGIN_NAMES: list[str] = []
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
_DISCOVERED_PLUGIN_ENTRIES: list[tuple[str, str]] = [] # (name, "module:attr"), populated once
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _discover_plugin_manifests() -> None:
|
|
21
|
+
"""Package-import-time step. Scans entry_points.txt ONLY (scan_entry_points) —
|
|
22
|
+
imports nothing, executes no plugin code.
|
|
23
|
+
|
|
24
|
+
Discovery goes through the ``entry_points.txt`` scanner (cheaper than a
|
|
25
|
+
fresh ``importlib.metadata.entry_points()`` scan per process; see
|
|
26
|
+
``_plugin_scan``), with a hard fallback to ``importlib.metadata`` on any
|
|
27
|
+
parse failure.
|
|
28
|
+
"""
|
|
29
|
+
import sys
|
|
30
|
+
|
|
31
|
+
from agent_runner._plugin_scan import scan_entry_points
|
|
32
|
+
|
|
33
|
+
global _DISCOVERED_PLUGIN_ENTRIES
|
|
34
|
+
_DISCOVERED_PLUGIN_ENTRIES = scan_entry_points(sys.path, _PLUGIN_GROUP)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
_discover_plugin_manifests()
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def load_and_register_plugins(plugins_cfg, log_dir=None) -> None:
|
|
41
|
+
"""Called from config.loader.load_config once [plugins] is parsed. For
|
|
42
|
+
each discovered (name, value) NOT in plugins_cfg.disable and not already
|
|
43
|
+
registered, resolve module_path/attr_path, import + register_manifest. A
|
|
44
|
+
disabled name is never imported. A per-plugin failure isolates as a
|
|
45
|
+
UserWarning and skips that ONE plugin; it never aborts the whole load.
|
|
46
|
+
|
|
47
|
+
``name`` here is always the entry-point name (the ``agent_runner.plugins``
|
|
48
|
+
pyproject.toml key) — it's the identifier known BEFORE import. It is NOT
|
|
49
|
+
necessarily ``PluginManifest.name`` (only known after import); for every
|
|
50
|
+
builtin the two are pinned equal by
|
|
51
|
+
``test_entry_point_names_should_match_manifest_name``, but that is not
|
|
52
|
+
enforced here.
|
|
53
|
+
|
|
54
|
+
``log_dir`` is accepted for call-site stability (config.loader threads it
|
|
55
|
+
through unconditionally) though this function no longer emits anything
|
|
56
|
+
itself.
|
|
57
|
+
"""
|
|
58
|
+
import warnings
|
|
59
|
+
|
|
60
|
+
from agent_runner._plugin_manifest import loaded_manifest_names, register_manifest
|
|
61
|
+
from agent_runner._registry import resolve_entry_target
|
|
62
|
+
|
|
63
|
+
disable = set(plugins_cfg.disable)
|
|
64
|
+
already = set(loaded_manifest_names())
|
|
65
|
+
for name, value in _DISCOVERED_PLUGIN_ENTRIES:
|
|
66
|
+
if name in disable or name in already:
|
|
67
|
+
continue
|
|
68
|
+
# An entry-point value may carry a trailing extras marker
|
|
69
|
+
# (``module:attr [extra1,extra2]``); importlib.metadata.EntryPoint's
|
|
70
|
+
# own module/attr grammar excludes "[", so anything from the first
|
|
71
|
+
# "[" onward is always extras, never part of the path — strip it
|
|
72
|
+
# before resolving, or it glues onto attr_path and breaks getattr().
|
|
73
|
+
stripped = value.partition("[")[0].rstrip()
|
|
74
|
+
module_path, _, attr_path = stripped.partition(":")
|
|
75
|
+
try:
|
|
76
|
+
target = resolve_entry_target(module_path, attr_path)
|
|
77
|
+
register_manifest(target)
|
|
78
|
+
except Exception as e: # noqa: BLE001 — a broken plugin must never crash the supervisor
|
|
79
|
+
warnings.warn(f"failed to load {_PLUGIN_GROUP} plugin {name!r}: {e}", stacklevel=3)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def apply_plugin_disable(names: list[str]) -> None:
|
|
83
|
+
"""Remove plugins matching ``names`` (manifest names) from all in-memory
|
|
84
|
+
registries.
|
|
85
|
+
|
|
86
|
+
Called after config-load to honor ``[plugins] disable``. Idempotent for
|
|
87
|
+
already-removed names. Emits a UserWarning for names that match no
|
|
88
|
+
loaded manifest (typo catcher; tolerates cross-env config drift).
|
|
89
|
+
|
|
90
|
+
A disabled name is never imported by ``load_and_register_plugins`` in the
|
|
91
|
+
first place, so this is belt-and-suspenders cleanup for anything that
|
|
92
|
+
reached the registries another way (e.g. a manifest registered directly
|
|
93
|
+
via ``register_manifest``, not through entry-point discovery).
|
|
94
|
+
"""
|
|
95
|
+
import warnings
|
|
96
|
+
|
|
97
|
+
from agent_runner._plugin_manifest import unregister_by_name
|
|
98
|
+
|
|
99
|
+
if not names:
|
|
100
|
+
return
|
|
101
|
+
|
|
102
|
+
global _DISABLED_PLUGIN_NAMES
|
|
103
|
+
_DISABLED_PLUGIN_NAMES = list(names)
|
|
104
|
+
|
|
105
|
+
found = unregister_by_name(set(names))
|
|
106
|
+
unknown = set(names) - found
|
|
107
|
+
if unknown:
|
|
108
|
+
warnings.warn(
|
|
109
|
+
f"[plugins] disable references unknown plugin name(s): {sorted(unknown)}. "
|
|
110
|
+
f"(Names matched no loaded PluginManifest; check spelling or installed packages.)",
|
|
111
|
+
stacklevel=2,
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def disabled_plugin_names() -> list[str]:
|
|
116
|
+
"""Names passed to the most recent ``apply_plugin_disable`` call.
|
|
117
|
+
|
|
118
|
+
Used by peek --json to surface ``plugins.disabled`` for operator visibility.
|
|
119
|
+
Returns the LIST (not set) preserving configured order.
|
|
120
|
+
"""
|
|
121
|
+
return list(_DISABLED_PLUGIN_NAMES)
|
|
@@ -29,6 +29,7 @@ from agent_runner.config import (
|
|
|
29
29
|
RuntimeConfig,
|
|
30
30
|
ScheduleConfig,
|
|
31
31
|
VcsConfig,
|
|
32
|
+
_HostHealthBrakeConfig,
|
|
32
33
|
_HostHealthDiskConfig,
|
|
33
34
|
_HostHealthMemoryConfig,
|
|
34
35
|
_HostHealthPressureConfig,
|
|
@@ -47,9 +48,8 @@ from agent_runner.monitor import AUTO_STOP_ALERTS, KNOWN_ALERT_KINDS
|
|
|
47
48
|
# (toml_section_name, dataclass, nested_sub_sections). Nesting is an EXPLICIT
|
|
48
49
|
# registry, not reflection, on two counts:
|
|
49
50
|
# - field name != TOML key: PhaseOverride.prompt_files is written as
|
|
50
|
-
# [phases.<name>.prompt] files=[...]
|
|
51
|
-
#
|
|
52
|
-
# not exist.
|
|
51
|
+
# [phases.<name>.prompt] files=[...]. Recursing generically would document
|
|
52
|
+
# TOML keys that do not exist.
|
|
53
53
|
# - typing.get_type_hints() raises TypeError on PhasesConfig — its `list`
|
|
54
54
|
# field shadows the builtin, so `list[str] | None` resolves against
|
|
55
55
|
# None. Do not reach for it here.
|
|
@@ -66,6 +66,7 @@ _SECTIONS: list[tuple[str, type, list[tuple[str, type]]]] = [
|
|
|
66
66
|
("monitor.host_health.disk", _HostHealthDiskConfig),
|
|
67
67
|
("monitor.host_health.memory", _HostHealthMemoryConfig),
|
|
68
68
|
("monitor.host_health.pressure", _HostHealthPressureConfig),
|
|
69
|
+
("monitor.host_health.brake", _HostHealthBrakeConfig),
|
|
69
70
|
],
|
|
70
71
|
),
|
|
71
72
|
("phases", PhasesConfig, []),
|
|
@@ -42,14 +42,6 @@ from agent_runner._emit.memory import ( # noqa: F401 — public re-export
|
|
|
42
42
|
emit_round_oom_killed,
|
|
43
43
|
emit_round_resumed,
|
|
44
44
|
)
|
|
45
|
-
from agent_runner._emit.plugins import ( # noqa: F401 — public re-export
|
|
46
|
-
emit_plugin_builtin_name_squat,
|
|
47
|
-
emit_plugin_checksum_mismatch,
|
|
48
|
-
emit_plugin_sandbox_degraded,
|
|
49
|
-
emit_plugin_sandbox_kill,
|
|
50
|
-
emit_plugin_spawn_decision,
|
|
51
|
-
emit_plugin_spawn_override_ignored,
|
|
52
|
-
)
|
|
53
45
|
from agent_runner._emit.rounds import ( # noqa: F401 — public re-export
|
|
54
46
|
emit_fresh_eyes_round_triggered,
|
|
55
47
|
emit_round_container_orphan_risk,
|
|
@@ -94,12 +86,6 @@ __all__ = [
|
|
|
94
86
|
"emit_memory_high_engaged",
|
|
95
87
|
"emit_memory_high_released",
|
|
96
88
|
"emit_memory_high_write_failed",
|
|
97
|
-
"emit_plugin_builtin_name_squat",
|
|
98
|
-
"emit_plugin_checksum_mismatch",
|
|
99
|
-
"emit_plugin_sandbox_degraded",
|
|
100
|
-
"emit_plugin_sandbox_kill",
|
|
101
|
-
"emit_plugin_spawn_decision",
|
|
102
|
-
"emit_plugin_spawn_override_ignored",
|
|
103
89
|
"emit_rate_limit_stop",
|
|
104
90
|
"emit_round_cgroup_memory",
|
|
105
91
|
"emit_round_container_orphan_risk",
|
|
@@ -217,13 +217,20 @@ def emit_round_oom_killed(
|
|
|
217
217
|
took, no second sysfs read). Symmetric with ``round_mem_terminated``
|
|
218
218
|
(supervisor-killed) -- this is the kernel-killed sibling.
|
|
219
219
|
|
|
220
|
-
POINTER-ONLY: ``log_path`` + ``log_bytes`` +
|
|
220
|
+
POINTER-ONLY: ``log_path`` + ``log_bytes`` + the oom-kill delta -- NEVER the
|
|
221
221
|
round-log/transcript content itself (durability, secret-redaction, size all
|
|
222
222
|
argue against embedding it in events.jsonl). ``partial_log`` reports whether
|
|
223
223
|
the supervisor's own truncation trailer (see ``_mark_partial_log``) was
|
|
224
224
|
written onto the round log, so a later reader can tell the log's tail is
|
|
225
225
|
supervisor residue, not the agent's own output.
|
|
226
226
|
|
|
227
|
+
The oom-kill delta rides under TWO field names with the identical value:
|
|
228
|
+
``events_oom_kill_delta`` is the canonical name (sibling-consistent with
|
|
229
|
+
``round_cgroup_memory``'s ``events_oom_kill_delta``); ``oom_kill_delta`` is
|
|
230
|
+
the retained legacy alias. The append-only event contract keeps both until a
|
|
231
|
+
future breaking release drops the bare alias -- so a single ``oom_kill_delta``
|
|
232
|
+
argument single-sources both fields, which can never diverge.
|
|
233
|
+
|
|
227
234
|
Classification is UNCHANGED by this event: the round still exits 137 and
|
|
228
235
|
counts toward the crash streak exactly as before -- this is pure
|
|
229
236
|
observability layered on top, computed and emitted after that decision is
|
|
@@ -236,6 +243,7 @@ def emit_round_oom_killed(
|
|
|
236
243
|
round_num=round_num,
|
|
237
244
|
log_path=str(log_path),
|
|
238
245
|
log_bytes=log_bytes,
|
|
246
|
+
events_oom_kill_delta=oom_kill_delta,
|
|
239
247
|
oom_kill_delta=oom_kill_delta,
|
|
240
248
|
partial_log=partial_log,
|
|
241
249
|
)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""Alert-kind catalog
|
|
1
|
+
"""Alert-kind catalog.
|
|
2
2
|
|
|
3
3
|
Pure bookkeeping: no filesystem I/O, no clock reads. Detector *logic* lives in
|
|
4
4
|
``_monitor_detectors``; state assembly in ``_monitor_state``; the cycle-edge
|
|
@@ -7,8 +7,7 @@ wiring (``run_all_detectors``/``on_alert``) in ``monitor.py``.
|
|
|
7
7
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
|
-
from agent_runner.
|
|
11
|
-
from agent_runner.api_types import Alert, Detector
|
|
10
|
+
from agent_runner.api_types import Alert
|
|
12
11
|
from agent_runner.config import _DEFAULT_AUTO_STOP_ON
|
|
13
12
|
from agent_runner.events import (
|
|
14
13
|
DETECTOR_ERROR,
|
|
@@ -82,17 +81,3 @@ def alert_identity(alert: Alert) -> str:
|
|
|
82
81
|
return alert.detector
|
|
83
82
|
parts = "|".join(f"{k}={alert.context.get(k)!r}" for k in fields)
|
|
84
83
|
return f"{alert.detector}:{parts}"
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
_PLUGIN_DETECTORS: list[Detector] = []
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
def register_detector(detector: Detector) -> None:
|
|
91
|
-
"""Register a plugin detector. Rejects duplicate names."""
|
|
92
|
-
ensure_unique(detector.name, _PLUGIN_DETECTORS, "detector")
|
|
93
|
-
_PLUGIN_DETECTORS.append(detector)
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
def plugin_detectors() -> list[str]:
|
|
97
|
-
"""Sorted list of registered plugin detector names (for peek --json)."""
|
|
98
|
-
return sorted(d.name for d in _PLUGIN_DETECTORS)
|
|
@@ -14,11 +14,12 @@ from dataclasses import dataclass, field
|
|
|
14
14
|
from pathlib import Path
|
|
15
15
|
from typing import Any
|
|
16
16
|
|
|
17
|
+
from agent_runner import event_log
|
|
18
|
+
from agent_runner._notify import NULL_LISTENER
|
|
17
19
|
from agent_runner.api_types import ProjectState, ServiceMode, ServiceStatus, SystemMetrics
|
|
18
20
|
from agent_runner.builtin_plugins._constants import _TAIL_LINES
|
|
19
|
-
from agent_runner.clock import SYSTEM_CLOCK
|
|
20
21
|
from agent_runner.context_store import read_json
|
|
21
|
-
from agent_runner.events import iter_event_dicts
|
|
22
|
+
from agent_runner.events import iter_event_dicts
|
|
22
23
|
|
|
23
24
|
|
|
24
25
|
@dataclass(frozen=True)
|
|
@@ -29,7 +30,7 @@ class LocalSource:
|
|
|
29
30
|
log_dir: Path
|
|
30
31
|
|
|
31
32
|
def events_files(self) -> list[Path]:
|
|
32
|
-
return
|
|
33
|
+
return event_log.all_month_files(self.log_dir)
|
|
33
34
|
|
|
34
35
|
def metrics_files(self) -> list[Path]:
|
|
35
36
|
return sorted(self.log_dir.glob("metrics-*.jsonl"))
|
|
@@ -75,7 +76,7 @@ class _EventTail:
|
|
|
75
76
|
)
|
|
76
77
|
|
|
77
78
|
def read(self, files: list[Path]) -> list[dict[str, Any]]:
|
|
78
|
-
new_events, self.offsets = read_new(files, self.offsets)
|
|
79
|
+
new_events, self.offsets = event_log.read_new(files, self.offsets)
|
|
79
80
|
self.buffer.extend(new_events)
|
|
80
81
|
return list(self.buffer)
|
|
81
82
|
|
|
@@ -93,23 +94,22 @@ def _tail_events_jsonl(
|
|
|
93
94
|
byte 0 of every file present at start (human-narrate use case).
|
|
94
95
|
|
|
95
96
|
Follows file rotation transparently — when a new events-YYYY-MM.jsonl
|
|
96
|
-
appears, it is picked up from byte 0.
|
|
97
|
+
appears, it is picked up from byte 0. A thin client over the shared
|
|
98
|
+
:func:`event_log.follow` loop (also used by ``events --tail``); polls
|
|
99
|
+
(``NULL_LISTENER`` -- no doorbell) rather than a live FIFO listener.
|
|
97
100
|
"""
|
|
98
|
-
|
|
101
|
+
seed: dict[Path, int] = {}
|
|
99
102
|
if start_at_now:
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
yield from new_events
|
|
111
|
-
else:
|
|
112
|
-
SYSTEM_CLOCK.sleep(poll_interval_s)
|
|
103
|
+
seed = event_log.seed_at_eof(event_log.all_month_files(log_dir))
|
|
104
|
+
|
|
105
|
+
for _line, obj in event_log.follow(
|
|
106
|
+
log_dir,
|
|
107
|
+
event_log.all_month_files,
|
|
108
|
+
wake=NULL_LISTENER,
|
|
109
|
+
timeout_s=poll_interval_s,
|
|
110
|
+
offsets=seed,
|
|
111
|
+
):
|
|
112
|
+
yield obj
|
|
113
113
|
|
|
114
114
|
|
|
115
115
|
_MAX_TAIL_FILES = 20
|
|
@@ -78,14 +78,9 @@ def drain(fd: int) -> None:
|
|
|
78
78
|
``select()`` on it instantly ready -- an undrained fd busy-spins its
|
|
79
79
|
caller at 100% CPU forever after the first wake, since a level-triggered
|
|
80
80
|
fd stays readable until read. Advisory: the bytes carry no payload and are
|
|
81
|
-
discarded.
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
(``_plugin_sandbox._run_child_process``, P3) drains the CALLER-OWNED wake fd
|
|
85
|
-
it was handed on the ``"woken"`` branch of its exit wait, before re-checking
|
|
86
|
-
``should_stop()`` -- that fd is the serve listener's, watched by
|
|
87
|
-
``wait_exit`` for the duration of the hook, so the trampoline must drain it
|
|
88
|
-
itself rather than leave the next wait instantly ready.
|
|
81
|
+
discarded. :meth:`Listener.wait` self-drains its own fd on the wake branch
|
|
82
|
+
(the pause/sleep waits ``_interruptible_sleep``/``_pause_poll`` are the
|
|
83
|
+
consumers of a live ``Listener``).
|
|
89
84
|
"""
|
|
90
85
|
while True:
|
|
91
86
|
try:
|
|
@@ -155,7 +155,7 @@ def _poll_once(
|
|
|
155
155
|
events = monitor.parse_events_from_jsonl_files(src.events_files())
|
|
156
156
|
metrics = monitor.parse_events_from_jsonl_files(src.metrics_files())
|
|
157
157
|
log_tails = monitor.load_round_log_tails(src.rounds_dir())
|
|
158
|
-
|
|
158
|
+
return monitor.run_all_detectors(
|
|
159
159
|
events=events,
|
|
160
160
|
metrics=metrics,
|
|
161
161
|
log_tails=log_tails,
|
|
@@ -167,11 +167,6 @@ def _poll_once(
|
|
|
167
167
|
host_health_cfg=cfg.monitor.host_health,
|
|
168
168
|
log_dir=cfg.runtime.log_dir,
|
|
169
169
|
)
|
|
170
|
-
if not monitor._PLUGIN_DETECTORS:
|
|
171
|
-
return builtin # skip ProjectState assembly when no plugins to feed
|
|
172
|
-
state = monitor.assemble_project_state(src, project=_project_name(work_dir))
|
|
173
|
-
plugin = monitor.run_plugin_detectors(state)
|
|
174
|
-
return builtin + plugin
|
|
175
170
|
|
|
176
171
|
|
|
177
172
|
def monitor_loop(
|