cli-agent-runner 0.3.2__tar.gz → 0.3.3__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.2 → cli_agent_runner-0.3.3}/.vulture-whitelist.py +2 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/CHANGELOG.md +6 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/PKG-INFO +1 -1
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_emit/memory.py +7 -1
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_plugin_manifest.py +14 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_version.py +2 -2
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/builtin_plugins/gemini.py +3 -1
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/cli/_serve_cgroup.py +14 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/cli/common.py +3 -1
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/cli/doctor_cmd.py +32 -1
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/metrics.py +33 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/docs/plugins.md +4 -3
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_import_footprint.py +5 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_no_version_refs.py +15 -8
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_peek_schema_version.py +1 -1
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_api_observation.py +25 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_cgroup_probe.py +219 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_doctor_cmd.py +33 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_plugin_manifest.py +39 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/.codecov.yml +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/.github/dependabot.yml +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/.github/workflows/ci.yml +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/.github/workflows/release.yml +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/.gitignore +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/BACKLOG.md +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/CODE_OF_CONDUCT.md +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/CONTRIBUTING.md +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/LICENSE +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/README.md +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/README.zh.md +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/SECURITY.md +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/__init__.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_docgen.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_emit/__init__.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_emit/agent.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_emit/plugins.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_emit/rounds.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_emit/serve.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_install.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_lifecycle.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_monitor_detectors.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_monitor_registry.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_monitor_state.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_observe.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_plugin_checksum.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_plugin_sandbox.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_plugin_scan.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_redact.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_registry.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_resolve.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_round_outcome.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_round_support.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_sandbox_probe.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_serve_policy.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_substrate.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_throttle.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/agent_runtime.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/api.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/api_types.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/builtin_plugins/__init__.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/builtin_plugins/_constants.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/builtin_plugins/claude_rate_limit.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/builtin_plugins/codewhale.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/builtin_plugins/default_dirty_handler.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/builtin_plugins/kimi.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/builtin_plugins/pi.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/cli/__init__.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/cli/__main__.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/cli/_serve_round.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/cli/events_cmd.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/cli/init_cmd.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/cli/install_cmd.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/cli/migrate_cmd.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/cli/monitor_cmd.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/cli/peek_cmd.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/cli/round_cmd.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/cli/serve_cmd.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/cli/service_cmd.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/cli/upgrade_cmd.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/clock.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/config/__init__.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/config/errors.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/config/loader.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/config/models.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/config/parsers.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/config/validators.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/context_store.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/defenses.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/events.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/hooks.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/host_health.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/http_progress.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/lifecycle.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/migrations.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/monitor.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/phase_select.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/presets/__init__.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/presets/aider.toml +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/presets/claude.toml +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/presets/codewhale.toml +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/presets/gemini.toml +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/presets/kimi.toml +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/presets/pi.toml +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/prompt_loader.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/remote_relay.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/round_log.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/round_view.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/runner.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/scaffold.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/schedule.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/service_unit.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/startup_check.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/vcs_state.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/build.sh +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/deploy/Dockerfile +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/deploy/docker-compose.yml +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/docs/README.md +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/docs/architecture.md +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/docs/commands.md +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/docs/configuration.md +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/docs/events.md +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/docs/long-running-agents.md +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/docs/memory-efficiency.md +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/docs/migrations/0.2.md +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/docs/migrations/0.3.md +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/docs/quickstart.md +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/docs/recipes/aider.md +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/docs/recipes/codewhale.md +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/docs/recipes/container-pi.md +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/docs/recipes/deploy-all-in-one.md +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/docs/recipes/kimi.md +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/docs/recipes/pi.md +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/docs/runbook.md +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/docs/thesis.md +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/pyproject.toml +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/__init__.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/_clock.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/_test_helpers.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/conftest.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/contract/__init__.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/contract/test_public_api_surface.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/e2e/__init__.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/e2e/conftest.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/e2e/test_e2e_graceful_stop.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/e2e/test_e2e_install_systemd.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/e2e/test_e2e_monitor_remote.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/e2e/test_e2e_round_lifecycle.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/fixtures/cli-real-output/claude-2.1.143-assistant-tool-use.jsonl +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/fixtures/cli-real-output/claude-2.1.143-result-event.jsonl +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/fixtures/cli-real-output/gemini-0.42.0-result-event.jsonl +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/generate_vulture_whitelist.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/integration/__init__.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/integration/test_auto_stop_e2e.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/integration/test_bounded_run.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/integration/test_context_enricher_namespacing.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/integration/test_dirty_handler_seam.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/integration/test_fresh_eyes_signal.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/integration/test_grace_kill_emission.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/integration/test_install_dry_run.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/integration/test_monitor_seeded.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/integration/test_plugin_detector_loaded.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/integration/test_plugin_owned_paths.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/integration/test_plugin_real_flow.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/integration/test_prompt_delivery_stdin.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/integration/test_run_one_round_with_fake_agent.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/integration/test_scaffold_presets.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/integration/test_serve_loop.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/integration/test_spawn_round_mem_floor.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/integration/test_spawn_round_wedged.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/integration/test_substrate_fingerprint.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/integration/test_transient_error_backoff.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/__init__.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/_docs.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/_event_scan.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_architecture.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_atomic_write_enforced.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_authored_facts_declared.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_auto_stop_policy_ssot.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_bdd_test_conventions.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_builtin_plugin_names_sync.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_catalogs.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_classification_ssot.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_config_error_consistency.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_config_value_set_ssot.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_container_stop_bound.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_dataclass_fields_have_producers.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_doc_builtin_plugins.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_doc_claims_match_ssot.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_doc_cli_claims.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_doc_operator_surface.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_doc_test_pointers_exist.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_doc_transient_error_claims.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_doc_usage_event_fields.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_docs_generated.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_docs_index_complete.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_entry_points_resolve.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_event_int_coercion.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_event_kind_registry.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_event_kinds_ssot.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_events_doc_contract.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_gen_blocks_name_their_source.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_hook_contract_docs.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_kill_tests_not_skipped.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_layer_2_loop_size.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_migrations_registry_ssot.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_module_boundaries.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_module_sizes.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_monitor_self_exclusion.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_no_ai_signatures.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_no_internal_refs.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_no_price_logic.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_no_pytest_skip_on_parse_fail.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_no_raw_time.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_no_vacuous_invariants.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_phase_select_stateless.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_plugins_config_stable.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_readme_zh_is_pointer.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_repo_constants_patched_in_tests.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_round_alloc_growth.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_round_log_decode_boundary.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_round_num_single_source.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_round_result_stable.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_set_diff_for_auto_tool_classification.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_stash_uses_sha_not_index.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_timeout_budget_invariant.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_upstream_schema_canary.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_vulture_whitelist_generated.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/linux/__init__.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/linux/test_plugin_sandbox_kill.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/literate/__init__.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/literate/parser.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/literate/test_parser.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/literate/test_quickstart.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/__init__.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_agent_runtime.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_agent_runtime_container.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_agent_runtime_grace.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_agent_runtime_marker_scan.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_agent_runtime_progress.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_agent_runtime_reap.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_agent_runtime_signal_name.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_api_assemble_prompt.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_api_events_stream.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_api_install.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_api_read_round_num.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_api_resolve_phase.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_api_service.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_api_types.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_auto_stop_gating.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_builtin_provenance.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_catalogs.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_claude_error_detector.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_claude_foreign_schema.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_cli.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_cli_common.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_cli_init_install.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_cli_main_boundary.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_cli_monitor_http.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_cli_service_peek_monitor.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_cli_upgrade.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_codewhale_code_precedence.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_codewhale_plugin.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_coerce_int_poison.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_collapse_spawn_decisions.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_config.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_config_fresh_eyes.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_config_max_rounds.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_config_nested_strictness.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_config_prompt_delivery.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_config_schedule.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_config_stop_file.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_config_strictness.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_config_substrate_fingerprint_paths.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_config_transient_error_action.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_context_store.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_control_char_config.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_default_dirty_handler.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_defenses.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_detect_hung_latch.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_detector_isolation.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_detector_protocol.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_dirty_handlers.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_dispatch_dirty_owner_branch.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_docgen.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_doctor_sandbox.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_effective_throttle_view.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_emit_config_migrated.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_emit_schedule.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_emit_schedule_phase_skipped.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_events.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_events_cmd.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_events_cmd_rollover.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_events_cmd_tail.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_events_jsonl_decode.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_example_dirty_handler.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_example_plugin.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_exec_prefix.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_exit_cause.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_exit_classifier.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_fresh_eyes_trigger.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_gate_serve_boot.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_gemini_plugin.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_git_timeout.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_hook_failure_isolation.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_hook_redact_order.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_hooks.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_host_health.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_http_progress.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_http_progress_epoch.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_init_entry_points.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_interruptible_sleep_should_stop.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_kimi_plugin.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_lifecycle.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_load_fail_closed.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_loader_split.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_manifest_spawn_hooks.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_metrics.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_metrics_cgroup_usage.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_metrics_swap.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_migrate_cmd.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_migrations.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_monitor_assembly.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_monitor_cmd_severity.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_monitor_dedup_identity.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_monitor_dedup_rearm.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_monitor_detect_anomaly_repetitive.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_monitor_detect_rate_limit.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_monitor_detect_supervisor_stale.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_monitor_detectors.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_monitor_event_tail.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_monitor_loop.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_monitor_on_alert.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_monitor_remote.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_monitor_round_deferred_stale.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_monitor_schedule_pause.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_network_blip_signal_guard.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_open_round_log.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_orphan_chain_single_pass.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_outer_round_ceiling.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_peek_argparse.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_peek_project_isolation.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_peek_sandbox_block.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_peek_schedule.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_peek_select.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_phase_agent_launch.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_phase_profiles.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_phase_select.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_pi_plugin.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_plugin_checksum.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_plugin_constants.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_plugin_name_mismatch.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_plugin_sandbox_wire.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_plugin_scan_parity.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_plugins_config_fields.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_presets.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_primary_prompt_file_home.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_prompt_loader.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_read_json_hardening.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_redact.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_resolve.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_round_cmd.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_round_cmd_sigterm.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_round_log_helpers.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_round_outcome.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_round_outcome_agent_axis.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_round_view.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_runner.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_runner_sidecar_ordering.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_runner_throttle.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_sandbox_probe.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_scaffold.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_schedule.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_serve_cmd_bounded.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_serve_config_broken.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_serve_crash_loop.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_serve_mem_gate.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_serve_phase_schedule.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_serve_policy.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_serve_round.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_serve_round_cgroup_spine.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_serve_round_log.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_serve_round_oom_killed.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_serve_round_terminate.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_serve_schedule_gate.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_serve_sentinel.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_serve_startup_hooks.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_service_mode.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_service_unit.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_spawn_seam.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_startup_battery_exit.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_startup_check.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_substrate.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_supervisor_stale_self_blind.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_throttle_back_off_ladder.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_throttle_epoch_bound.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_throttle_plugin_classification.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_upgrade_migrate.py +0 -0
- {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_vcs_state.py +0 -0
|
@@ -23,6 +23,7 @@ dirty_handlers
|
|
|
23
23
|
spawn_hooks
|
|
24
24
|
detectors
|
|
25
25
|
event_kinds
|
|
26
|
+
sigterm_cooperative
|
|
26
27
|
|
|
27
28
|
# agent_runner._round_outcome.RoundOutcome
|
|
28
29
|
mem_terminated
|
|
@@ -156,6 +157,7 @@ checks
|
|
|
156
157
|
overlaps
|
|
157
158
|
plan
|
|
158
159
|
sandbox
|
|
160
|
+
cgroup
|
|
159
161
|
|
|
160
162
|
# agent_runner.config.models.AgentConfig
|
|
161
163
|
command
|
|
@@ -5,6 +5,12 @@ 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.3] - 2026-09-14
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- `host_cgroup_memory_limit` now reports whether the supervisor's own cgroup is delegated (its `cgroup.procs`/`memory.high` are writable); `doctor` shows it and advises adding `Delegate=yes` to the systemd unit when it isn't. Read-only — nothing is written to any cgroup.
|
|
12
|
+
- Plugin presets can declare `sigterm_cooperative` (the built-in `gemini` preset does); an observability-only declaration surfaced in `peek --json` (schema `2.3`) and `doctor` — it does not change any termination behavior.
|
|
13
|
+
|
|
8
14
|
## [0.3.2] - 2026-09-14
|
|
9
15
|
|
|
10
16
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: cli-agent-runner
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.3
|
|
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
|
|
@@ -106,6 +106,7 @@ def emit_host_cgroup_memory_limit(
|
|
|
106
106
|
swap_cap_pct: float | None = None,
|
|
107
107
|
memory_high: int | None = None,
|
|
108
108
|
advisory: str | None = None,
|
|
109
|
+
cgroup_delegated: bool | None = None,
|
|
109
110
|
) -> None:
|
|
110
111
|
"""Emit once at serve startup: this process's cgroup v2 memory budget
|
|
111
112
|
(``metrics.cgroup_memory_limits``). ``None`` fields mean unlimited (or
|
|
@@ -128,7 +129,11 @@ def emit_host_cgroup_memory_limit(
|
|
|
128
129
|
fire: a ``memory.swap.max`` that looks implausibly tight against host
|
|
129
130
|
swap, and a ``memory.max`` set on this process's OWN cgroup without a
|
|
130
131
|
``memory.high``, which recommends adding one (below ``memory.max``) for
|
|
131
|
-
graceful pre-OOM throttling instead of a hard kill.
|
|
132
|
+
graceful pre-OOM throttling instead of a hard kill. ``cgroup_delegated``
|
|
133
|
+
(``metrics.cgroup_delegated``) is the READ-ONLY delegation-readiness
|
|
134
|
+
probe: ``True``/``False`` when cgroup v2 is present, ``None`` when it
|
|
135
|
+
isn't or the leaf couldn't be resolved -- an append-only field, unrelated
|
|
136
|
+
to whether the floor defers."""
|
|
132
137
|
from agent_runner.events import HOST_CGROUP_MEMORY_LIMIT, emit
|
|
133
138
|
|
|
134
139
|
emit(
|
|
@@ -141,6 +146,7 @@ def emit_host_cgroup_memory_limit(
|
|
|
141
146
|
swap_cap_pct=swap_cap_pct,
|
|
142
147
|
memory_high=memory_high,
|
|
143
148
|
advisory=advisory,
|
|
149
|
+
cgroup_delegated=cgroup_delegated,
|
|
144
150
|
)
|
|
145
151
|
|
|
146
152
|
|
|
@@ -36,6 +36,12 @@ class PluginManifest:
|
|
|
36
36
|
spawn_hooks: tuple[SpawnHook, ...] = ()
|
|
37
37
|
detectors: tuple[Detector, ...] = ()
|
|
38
38
|
event_kinds: tuple[str, ...] = ()
|
|
39
|
+
sigterm_cooperative: bool = False
|
|
40
|
+
"""Declares that this preset's CLI cooperatively drains/cleans up on
|
|
41
|
+
SIGTERM -- source-verified per preset, NEVER assumed from a CLI's
|
|
42
|
+
general reputation. Observability-only: surfaced via
|
|
43
|
+
cooperative_manifest_names() to `peek --json` and `doctor`. Does not
|
|
44
|
+
itself change any termination behavior."""
|
|
39
45
|
|
|
40
46
|
|
|
41
47
|
_LOADED_MANIFESTS: list[PluginManifest] = []
|
|
@@ -48,6 +54,14 @@ def loaded_manifest_names() -> list[str]:
|
|
|
48
54
|
return [m.name for m in _LOADED_MANIFESTS]
|
|
49
55
|
|
|
50
56
|
|
|
57
|
+
def cooperative_manifest_names() -> list[str]:
|
|
58
|
+
"""Names of every currently-registered manifest declaring
|
|
59
|
+
sigterm_cooperative=True (order-preserving). Mirrors
|
|
60
|
+
loaded_manifest_names; used by peek + doctor to answer "which presets
|
|
61
|
+
are cooperative" without either caller reaching into _LOADED_MANIFESTS."""
|
|
62
|
+
return [m.name for m in _LOADED_MANIFESTS if m.sigterm_cooperative]
|
|
63
|
+
|
|
64
|
+
|
|
51
65
|
def register_manifest(
|
|
52
66
|
manifest: PluginManifest,
|
|
53
67
|
*,
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '0.3.
|
|
22
|
-
__version_tuple__ = version_tuple = (0, 3,
|
|
21
|
+
__version__ = version = '0.3.3'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 3, 3)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -162,4 +162,6 @@ def _extract_usage(stats: dict[str, Any]) -> dict[str, Any]:
|
|
|
162
162
|
}
|
|
163
163
|
|
|
164
164
|
|
|
165
|
-
PLUGIN = PluginManifest(
|
|
165
|
+
PLUGIN = PluginManifest(
|
|
166
|
+
name="gemini", post_round_hooks=(GeminiErrorDetector(),), sigterm_cooperative=True
|
|
167
|
+
)
|
|
@@ -190,6 +190,16 @@ def _maybe_emit_oom_killed(
|
|
|
190
190
|
# report ask #3). Advisory only -- never changes the operator's cgroup/unit.
|
|
191
191
|
_SWAP_CAP_ADVISORY_PCT = 25.0
|
|
192
192
|
|
|
193
|
+
# The delegation-readiness advisory: memory.max/memory.high are bound on this
|
|
194
|
+
# cgroup, but metrics.cgroup_delegated found the leaf is NOT delegated
|
|
195
|
+
# (systemd Delegate=yes) -- a future release that wants to write memory.high
|
|
196
|
+
# on a round-scoped nested cgroup needs delegation first. Advisory only; this
|
|
197
|
+
# probe and its hint never write to the cgroup or the unit.
|
|
198
|
+
_UNDELEGATED_HINT = (
|
|
199
|
+
"this cgroup is not delegated (systemd Delegate=yes) -- memory.high can be "
|
|
200
|
+
"read but not managed here until it is"
|
|
201
|
+
)
|
|
202
|
+
|
|
193
203
|
|
|
194
204
|
def _probe_and_emit_cgroup_defer(log_dir: Path) -> bool:
|
|
195
205
|
"""Probe this process's cgroup v2 memory budget once at serve startup,
|
|
@@ -252,6 +262,7 @@ def _probe_and_emit_cgroup_defer(log_dir: Path) -> bool:
|
|
|
252
262
|
# `self_cgroup=limits["cgroup_path"]` dead-ends at the same place either
|
|
253
263
|
# way as calling with no override would.
|
|
254
264
|
memory_high = metrics.cgroup_memory_high(self_cgroup=limits["cgroup_path"])
|
|
265
|
+
delegated = metrics.cgroup_delegated(self_cgroup=limits["cgroup_path"])
|
|
255
266
|
swap_max = limits["memory_swap_max"]
|
|
256
267
|
swap_cap_pct = (
|
|
257
268
|
round(100.0 * swap_max / swap_total, 1) if swap_max is not None and swap_total > 0 else None
|
|
@@ -288,6 +299,8 @@ def _probe_and_emit_cgroup_defer(log_dir: Path) -> bool:
|
|
|
288
299
|
"throttle's PSI-full rise doesn't trip the mid-round floor"
|
|
289
300
|
)
|
|
290
301
|
advisories.append(hint)
|
|
302
|
+
if delegated is False and (memory_high is not None or own_scope):
|
|
303
|
+
advisories.append(_UNDELEGATED_HINT)
|
|
291
304
|
advisory = "; ".join(advisories) or None
|
|
292
305
|
if advisory is not None:
|
|
293
306
|
print(f"agent-runner: {advisory}", file=sys.stderr)
|
|
@@ -300,5 +313,6 @@ def _probe_and_emit_cgroup_defer(log_dir: Path) -> bool:
|
|
|
300
313
|
swap_cap_pct=swap_cap_pct,
|
|
301
314
|
memory_high=memory_high,
|
|
302
315
|
advisory=advisory,
|
|
316
|
+
cgroup_delegated=delegated,
|
|
303
317
|
)
|
|
304
318
|
return defer
|
|
@@ -19,7 +19,7 @@ from agent_runner.hooks import plugin_context_enrichers, post_round_hooks, pre_r
|
|
|
19
19
|
from agent_runner.monitor import plugin_detectors
|
|
20
20
|
from agent_runner.vcs_state import plugin_owned_paths
|
|
21
21
|
|
|
22
|
-
PEEK_SCHEMA_VERSION = "2.
|
|
22
|
+
PEEK_SCHEMA_VERSION = "2.3"
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
def cfg_from_args(args) -> Config:
|
|
@@ -98,6 +98,7 @@ def emit(value: Any, *, json_mode: bool, cfg: Config | None = None) -> None:
|
|
|
98
98
|
if json_mode:
|
|
99
99
|
if isinstance(value, ProjectState):
|
|
100
100
|
from agent_runner import _sandbox_probe, disabled_plugin_names
|
|
101
|
+
from agent_runner._plugin_manifest import cooperative_manifest_names
|
|
101
102
|
|
|
102
103
|
plugins_block = {
|
|
103
104
|
"event_kinds": plugin_event_kinds(),
|
|
@@ -107,6 +108,7 @@ def emit(value: Any, *, json_mode: bool, cfg: Config | None = None) -> None:
|
|
|
107
108
|
"detectors": plugin_detectors(),
|
|
108
109
|
"owned_paths": plugin_owned_paths(),
|
|
109
110
|
"disabled": disabled_plugin_names(),
|
|
111
|
+
"sigterm_cooperative": cooperative_manifest_names(),
|
|
110
112
|
}
|
|
111
113
|
if cfg is not None:
|
|
112
114
|
plugins_block.update(_sandbox_probe.peek_snapshot(cfg))
|
|
@@ -6,7 +6,7 @@ from __future__ import annotations
|
|
|
6
6
|
|
|
7
7
|
from dataclasses import dataclass
|
|
8
8
|
|
|
9
|
-
from agent_runner import phase_select, startup_check
|
|
9
|
+
from agent_runner import _plugin_manifest, phase_select, startup_check
|
|
10
10
|
from agent_runner.cli.common import cfg_from_args, emit
|
|
11
11
|
|
|
12
12
|
|
|
@@ -16,6 +16,7 @@ class DoctorReport:
|
|
|
16
16
|
overlaps: list[phase_select.WindowOverlap]
|
|
17
17
|
plan: list[dict]
|
|
18
18
|
sandbox: dict
|
|
19
|
+
cgroup: dict
|
|
19
20
|
|
|
20
21
|
|
|
21
22
|
def add_parser(sub, parent) -> None:
|
|
@@ -43,6 +44,23 @@ def _plan(cfg, rounds: int) -> list[dict]:
|
|
|
43
44
|
return out
|
|
44
45
|
|
|
45
46
|
|
|
47
|
+
def _cgroup_report() -> dict:
|
|
48
|
+
"""Read-only cgroup delegation-readiness snapshot for `doctor` -- never
|
|
49
|
+
emits an event (unlike serve's `_probe_and_emit_cgroup_defer`, which
|
|
50
|
+
shares the same underlying `metrics` probes but writes
|
|
51
|
+
`host_cgroup_memory_limit`). `doctor` never launches the agent or writes
|
|
52
|
+
anything; this section is the same discipline applied to cgroup state."""
|
|
53
|
+
from agent_runner import metrics
|
|
54
|
+
|
|
55
|
+
limits = metrics.cgroup_memory_limits()
|
|
56
|
+
return {
|
|
57
|
+
"cgroup_path": limits["cgroup_path"],
|
|
58
|
+
"memory_max": limits["memory_max"],
|
|
59
|
+
"memory_high": metrics.cgroup_memory_high(self_cgroup=limits["cgroup_path"]),
|
|
60
|
+
"delegated": metrics.cgroup_delegated(self_cgroup=limits["cgroup_path"]),
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
|
|
46
64
|
def cmd_doctor(args) -> int:
|
|
47
65
|
from agent_runner._sandbox_probe import doctor_snapshot
|
|
48
66
|
|
|
@@ -52,6 +70,7 @@ def cmd_doctor(args) -> int:
|
|
|
52
70
|
overlaps=phase_select.find_phase_window_overlaps(cfg),
|
|
53
71
|
plan=_plan(cfg, args.rounds),
|
|
54
72
|
sandbox=doctor_snapshot(cfg),
|
|
73
|
+
cgroup=_cgroup_report(),
|
|
55
74
|
)
|
|
56
75
|
json_mode = getattr(args, "json", False)
|
|
57
76
|
if json_mode:
|
|
@@ -101,4 +120,16 @@ def _format(report: DoctorReport) -> str:
|
|
|
101
120
|
lines.append(" third-party plugin checksums (paste into [plugins.pin]):")
|
|
102
121
|
for name, digest in sorted(hashes.items()):
|
|
103
122
|
lines.append(f' {name} = "{digest}"')
|
|
123
|
+
cooperative = _plugin_manifest.cooperative_manifest_names()
|
|
124
|
+
lines.append(f"cooperative presets: {', '.join(sorted(cooperative)) or '(none)'}")
|
|
125
|
+
cgroup = report.cgroup
|
|
126
|
+
lines.append("cgroup:")
|
|
127
|
+
lines.append(f" cgroup_path: {cgroup['cgroup_path']}")
|
|
128
|
+
lines.append(f" memory_max: {cgroup['memory_max']}")
|
|
129
|
+
lines.append(f" memory_high: {cgroup['memory_high']}")
|
|
130
|
+
lines.append(f" delegated: {cgroup['delegated']}")
|
|
131
|
+
if cgroup["delegated"] is False:
|
|
132
|
+
from agent_runner.cli._serve_cgroup import _UNDELEGATED_HINT
|
|
133
|
+
|
|
134
|
+
lines.append(f" hint: {_UNDELEGATED_HINT}")
|
|
104
135
|
return "\n".join(lines)
|
|
@@ -362,6 +362,39 @@ def cgroup_memory_high(
|
|
|
362
362
|
return _min_ancestor_limit(root, ancestors, "memory.high")
|
|
363
363
|
|
|
364
364
|
|
|
365
|
+
def cgroup_delegated(
|
|
366
|
+
*,
|
|
367
|
+
root: Path = _CGROUP_ROOT,
|
|
368
|
+
proc_self_cgroup: Path = _PROC_SELF_CGROUP,
|
|
369
|
+
self_cgroup: str | None = None,
|
|
370
|
+
) -> bool | None:
|
|
371
|
+
"""Whether THIS process's own cgroup v2 leaf is delegated to it: uid-owned
|
|
372
|
+
AND both cgroup.procs and memory.high are writable. Read-only -- tests
|
|
373
|
+
writability via os.access(path, os.W_OK) against the existing directory;
|
|
374
|
+
NEVER opens, creates, or writes either file. None when cgroup v2 is
|
|
375
|
+
unavailable or the leaf can't be resolved (mirrors cgroup_path=None
|
|
376
|
+
elsewhere in this module) -- distinct from False (cgroup v2 present,
|
|
377
|
+
but NOT delegated to this process).
|
|
378
|
+
|
|
379
|
+
Delegation (systemd's Delegate=yes) is the prerequisite a future release
|
|
380
|
+
needs before it may safely write memory.high on a round-scoped nested
|
|
381
|
+
cgroup -- this probe only ever answers the readiness question; it never
|
|
382
|
+
itself writes anything.
|
|
383
|
+
"""
|
|
384
|
+
resolved = _resolve_cgroup(root, proc_self_cgroup, self_cgroup)
|
|
385
|
+
if resolved is None:
|
|
386
|
+
return None
|
|
387
|
+
cgroup_path, _ancestors = resolved
|
|
388
|
+
leaf_dir = root / cgroup_path.lstrip("/")
|
|
389
|
+
try:
|
|
390
|
+
uid_owned = leaf_dir.stat().st_uid == os.getuid()
|
|
391
|
+
except OSError:
|
|
392
|
+
return None
|
|
393
|
+
procs_writable = os.access(leaf_dir / "cgroup.procs", os.W_OK)
|
|
394
|
+
high_writable = os.access(leaf_dir / "memory.high", os.W_OK)
|
|
395
|
+
return uid_owned and procs_writable and high_writable
|
|
396
|
+
|
|
397
|
+
|
|
365
398
|
def cgroup_memory_usage(
|
|
366
399
|
*,
|
|
367
400
|
root: Path = _CGROUP_ROOT,
|
|
@@ -188,14 +188,15 @@ The round itself continues — a broken plugin must not crash the supervisor.
|
|
|
188
188
|
|
|
189
189
|
```json
|
|
190
190
|
{
|
|
191
|
-
"schema_version": "2.
|
|
191
|
+
"schema_version": "2.3",
|
|
192
192
|
"plugins": {
|
|
193
193
|
"event_kinds": [...],
|
|
194
194
|
"context_enrichers": ["current_branch"],
|
|
195
195
|
"pre_round_hooks": [...],
|
|
196
196
|
"post_round_hooks": [...],
|
|
197
197
|
"detectors": [...],
|
|
198
|
-
"owned_paths": [...]
|
|
198
|
+
"owned_paths": [...],
|
|
199
|
+
"sigterm_cooperative": ["gemini"]
|
|
199
200
|
},
|
|
200
201
|
...
|
|
201
202
|
}
|
|
@@ -549,7 +550,7 @@ detector. Other plugin detectors and all builtins still run normally.
|
|
|
549
550
|
|
|
550
551
|
```json
|
|
551
552
|
{
|
|
552
|
-
"schema_version": "2.
|
|
553
|
+
"schema_version": "2.3",
|
|
553
554
|
"plugins": {
|
|
554
555
|
"event_kinds": [...],
|
|
555
556
|
"context_enrichers": [...],
|
|
@@ -126,6 +126,11 @@ EXPECTED_STARTUP_PKG_MODULES = frozenset(
|
|
|
126
126
|
# startup_check, cli.common) were ALL already in this allowlist -- it adds
|
|
127
127
|
# no new transitive dependency, just this one module itself.
|
|
128
128
|
"agent_runner.cli.doctor_cmd",
|
|
129
|
+
# _plugin_manifest: doctor_cmd's new module-level import (cooperative
|
|
130
|
+
# presets line). Its own imports (_registry, api_types, hooks) were ALL
|
|
131
|
+
# already in this allowlist -- adds no new transitive dependency, just
|
|
132
|
+
# this one module itself.
|
|
133
|
+
"agent_runner._plugin_manifest",
|
|
129
134
|
"agent_runner.cli.events_cmd",
|
|
130
135
|
"agent_runner.cli.init_cmd",
|
|
131
136
|
"agent_runner.cli.install_cmd",
|
|
@@ -5,7 +5,7 @@ planning task added a piece of code, in two related shapes:
|
|
|
5
5
|
|
|
6
6
|
- a release version number, e.g. "0.2.17 Task 1" / "pre-0.2.18"
|
|
7
7
|
- a bare internal-dev tag with no version number at all, e.g. "Group C,
|
|
8
|
-
seam 3" / "Group A" / "Task 5" on its own
|
|
8
|
+
seam 3" / "Group A" / "Task 5" / "Component 3" on its own
|
|
9
9
|
|
|
10
10
|
Neither shape ever drove any logic (no version comparisons or branches
|
|
11
11
|
existed anywhere, and no code ever switched on a group/task/seam label), and
|
|
@@ -51,17 +51,18 @@ _REPO = Path(__file__).resolve().parents[2]
|
|
|
51
51
|
# contains "0.0.1", which would otherwise match this pattern) -- OR a bare
|
|
52
52
|
# SDD-planning tag. The SDD-tag alternatives are anchored on the exact shapes
|
|
53
53
|
# actually used (a single capital letter after "Group"; a number after
|
|
54
|
-
# "Task"/"seam") so ordinary English -- "a group of tests", "the
|
|
55
|
-
# queue", "process group", "a watertight seam"
|
|
56
|
-
# Alpha" fails because `\b` cannot land
|
|
57
|
-
# and "l", and a bare "task"/"seam"
|
|
58
|
-
# all.
|
|
54
|
+
# "Task"/"seam"/"Component") so ordinary English -- "a group of tests", "the
|
|
55
|
+
# task queue", "process group", "a watertight seam", "a component of the
|
|
56
|
+
# system" -- never matches: "Group Alpha" fails because `\b` cannot land
|
|
57
|
+
# between the two word characters "A" and "l", and a bare "task"/"seam"/
|
|
58
|
+
# "component" with no following digit never matches at all.
|
|
59
59
|
_BREADCRUMB_REF = re.compile(
|
|
60
60
|
r"(?<![\d.])0\.[0-9]+\.[0-9]+\b" # release version, e.g. "0.2.17"
|
|
61
61
|
r"|(?<![\d.])pre-0\.[0-9]" # "pre-0.2.18"
|
|
62
62
|
r"|\bGroup [A-Z]\b" # SDD group label, e.g. "Group C"
|
|
63
63
|
r"|\bTask [0-9]+" # SDD task label, e.g. "Task 5"
|
|
64
64
|
r"|\bseam [0-9]+" # SDD seam label, e.g. "seam 3"
|
|
65
|
+
r"|\bComponent [0-9]+" # SDD component label, e.g. "Component 3"
|
|
65
66
|
)
|
|
66
67
|
|
|
67
68
|
_ALLOWLIST_FILES = {
|
|
@@ -138,6 +139,10 @@ def test_scanner_should_flag_reintroduced_sdd_tag_when_scanned(tmp_path: Path) -
|
|
|
138
139
|
group_only.write_text('"""The round-child exit-code CLASSIFIER (Group A)."""\n')
|
|
139
140
|
assert _scan([group_only]), "scanner failed to flag a reintroduced bare 'Group A' tag"
|
|
140
141
|
|
|
142
|
+
component = tmp_path / "component_module.py"
|
|
143
|
+
component.write_text('"""Read by wrapup_grace_s (cli/_serve_round.py, Component 3)."""\n')
|
|
144
|
+
assert _scan([component]), "scanner failed to flag a reintroduced 'Component 3' tag"
|
|
145
|
+
|
|
141
146
|
clean = tmp_path / "clean_module.py"
|
|
142
147
|
clean.write_text('"""The round-child exit-code CLASSIFIER."""\n')
|
|
143
148
|
assert not _scan([clean]), "scanner false-positived on tag-free text"
|
|
@@ -158,8 +163,9 @@ def test_scanner_should_not_flag_ordinary_english_group_task_seam_when_scanned(
|
|
|
158
163
|
"""The SDD-tag patterns must not fire on genuine domain/English usage of
|
|
159
164
|
the same words -- "process group" and "a group of X" (real usage
|
|
160
165
|
elsewhere in this codebase, e.g. defenses.py's "process group reaping"),
|
|
161
|
-
a plain "task queue",
|
|
162
|
-
|
|
166
|
+
a plain "task queue", "seam" used as an ordinary noun with no following
|
|
167
|
+
digit, and "component" used as an ordinary noun (e.g. "a component of
|
|
168
|
+
the system") with no following digit."""
|
|
163
169
|
english = tmp_path / "english_module.py"
|
|
164
170
|
english.write_text(
|
|
165
171
|
"\n".join(
|
|
@@ -168,6 +174,7 @@ def test_scanner_should_not_flag_ordinary_english_group_task_seam_when_scanned(
|
|
|
168
174
|
"",
|
|
169
175
|
"A group of background tasks share a task queue; the seam between",
|
|
170
176
|
"two panels must stay watertight. Group Alpha handles retries.",
|
|
177
|
+
"This module is a component of the larger system.",
|
|
171
178
|
'"""',
|
|
172
179
|
"",
|
|
173
180
|
]
|
{cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_peek_schema_version.py
RENAMED
|
@@ -72,7 +72,7 @@ def test_peek_json_should_include_schema_version_when_emitted(tmp_path: Path) ->
|
|
|
72
72
|
f"schema_version regressed: got {payload['schema_version']!r}, "
|
|
73
73
|
f"expected >= {PEEK_SCHEMA_VERSION!r}"
|
|
74
74
|
)
|
|
75
|
-
assert payload["schema_version"] == "2.
|
|
75
|
+
assert payload["schema_version"] == "2.3"
|
|
76
76
|
assert "plugins" in payload
|
|
77
77
|
assert isinstance(payload["plugins"], dict)
|
|
78
78
|
assert "event_kinds" in payload["plugins"]
|
|
@@ -617,3 +617,28 @@ def test_emit_should_include_disabled_plugins_block_when_json_mode(
|
|
|
617
617
|
assert "disabled" in out["plugins"]
|
|
618
618
|
# Default empty list when no apply_plugin_disable was called
|
|
619
619
|
assert isinstance(out["plugins"]["disabled"], list)
|
|
620
|
+
|
|
621
|
+
|
|
622
|
+
def test_emit_should_include_sigterm_cooperative_plugins_block_when_json_mode(
|
|
623
|
+
tmp_git_repo: Path,
|
|
624
|
+
capsys,
|
|
625
|
+
) -> None:
|
|
626
|
+
from agent_runner.api_types import ProjectState, ServiceMode, ServiceStatus, SystemMetrics
|
|
627
|
+
from agent_runner.cli.common import emit
|
|
628
|
+
|
|
629
|
+
state = ProjectState(
|
|
630
|
+
project="t",
|
|
631
|
+
status={},
|
|
632
|
+
defenses=[],
|
|
633
|
+
current_round=None,
|
|
634
|
+
recent_rounds=[],
|
|
635
|
+
orphan=None,
|
|
636
|
+
system=SystemMetrics(mem_total_mb=1, mem_available_mb=1, disk_used_pct=0.0),
|
|
637
|
+
service=ServiceStatus(mode=ServiceMode.NONE, active=False),
|
|
638
|
+
)
|
|
639
|
+
|
|
640
|
+
emit(state, json_mode=True)
|
|
641
|
+
|
|
642
|
+
out = json.loads(capsys.readouterr().out)
|
|
643
|
+
assert "sigterm_cooperative" in out["plugins"]
|
|
644
|
+
assert isinstance(out["plugins"]["sigterm_cooperative"], list)
|