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.
Files changed (402) hide show
  1. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/.vulture-whitelist.py +2 -0
  2. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/CHANGELOG.md +6 -0
  3. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/PKG-INFO +1 -1
  4. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_emit/memory.py +7 -1
  5. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_plugin_manifest.py +14 -0
  6. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_version.py +2 -2
  7. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/builtin_plugins/gemini.py +3 -1
  8. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/cli/_serve_cgroup.py +14 -0
  9. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/cli/common.py +3 -1
  10. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/cli/doctor_cmd.py +32 -1
  11. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/metrics.py +33 -0
  12. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/docs/plugins.md +4 -3
  13. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_import_footprint.py +5 -0
  14. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_no_version_refs.py +15 -8
  15. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_peek_schema_version.py +1 -1
  16. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_api_observation.py +25 -0
  17. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_cgroup_probe.py +219 -0
  18. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_doctor_cmd.py +33 -0
  19. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_plugin_manifest.py +39 -0
  20. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/.codecov.yml +0 -0
  21. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  22. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  23. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  24. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  25. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/.github/dependabot.yml +0 -0
  26. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/.github/workflows/ci.yml +0 -0
  27. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/.github/workflows/release.yml +0 -0
  28. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/.gitignore +0 -0
  29. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/BACKLOG.md +0 -0
  30. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/CODE_OF_CONDUCT.md +0 -0
  31. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/CONTRIBUTING.md +0 -0
  32. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/LICENSE +0 -0
  33. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/README.md +0 -0
  34. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/README.zh.md +0 -0
  35. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/SECURITY.md +0 -0
  36. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/__init__.py +0 -0
  37. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_docgen.py +0 -0
  38. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_emit/__init__.py +0 -0
  39. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_emit/agent.py +0 -0
  40. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_emit/plugins.py +0 -0
  41. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_emit/rounds.py +0 -0
  42. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_emit/serve.py +0 -0
  43. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_install.py +0 -0
  44. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_lifecycle.py +0 -0
  45. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_monitor_detectors.py +0 -0
  46. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_monitor_registry.py +0 -0
  47. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_monitor_state.py +0 -0
  48. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_observe.py +0 -0
  49. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_plugin_checksum.py +0 -0
  50. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_plugin_sandbox.py +0 -0
  51. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_plugin_scan.py +0 -0
  52. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_redact.py +0 -0
  53. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_registry.py +0 -0
  54. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_resolve.py +0 -0
  55. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_round_outcome.py +0 -0
  56. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_round_support.py +0 -0
  57. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_sandbox_probe.py +0 -0
  58. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_serve_policy.py +0 -0
  59. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_substrate.py +0 -0
  60. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/_throttle.py +0 -0
  61. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/agent_runtime.py +0 -0
  62. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/api.py +0 -0
  63. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/api_types.py +0 -0
  64. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/builtin_plugins/__init__.py +0 -0
  65. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/builtin_plugins/_constants.py +0 -0
  66. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/builtin_plugins/claude_rate_limit.py +0 -0
  67. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/builtin_plugins/codewhale.py +0 -0
  68. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/builtin_plugins/default_dirty_handler.py +0 -0
  69. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/builtin_plugins/kimi.py +0 -0
  70. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/builtin_plugins/pi.py +0 -0
  71. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/cli/__init__.py +0 -0
  72. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/cli/__main__.py +0 -0
  73. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/cli/_serve_round.py +0 -0
  74. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/cli/events_cmd.py +0 -0
  75. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/cli/init_cmd.py +0 -0
  76. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/cli/install_cmd.py +0 -0
  77. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/cli/migrate_cmd.py +0 -0
  78. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/cli/monitor_cmd.py +0 -0
  79. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/cli/peek_cmd.py +0 -0
  80. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/cli/round_cmd.py +0 -0
  81. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/cli/serve_cmd.py +0 -0
  82. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/cli/service_cmd.py +0 -0
  83. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/cli/upgrade_cmd.py +0 -0
  84. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/clock.py +0 -0
  85. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/config/__init__.py +0 -0
  86. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/config/errors.py +0 -0
  87. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/config/loader.py +0 -0
  88. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/config/models.py +0 -0
  89. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/config/parsers.py +0 -0
  90. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/config/validators.py +0 -0
  91. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/context_store.py +0 -0
  92. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/defenses.py +0 -0
  93. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/events.py +0 -0
  94. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/hooks.py +0 -0
  95. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/host_health.py +0 -0
  96. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/http_progress.py +0 -0
  97. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/lifecycle.py +0 -0
  98. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/migrations.py +0 -0
  99. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/monitor.py +0 -0
  100. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/phase_select.py +0 -0
  101. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/presets/__init__.py +0 -0
  102. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/presets/aider.toml +0 -0
  103. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/presets/claude.toml +0 -0
  104. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/presets/codewhale.toml +0 -0
  105. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/presets/gemini.toml +0 -0
  106. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/presets/kimi.toml +0 -0
  107. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/presets/pi.toml +0 -0
  108. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/prompt_loader.py +0 -0
  109. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/remote_relay.py +0 -0
  110. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/round_log.py +0 -0
  111. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/round_view.py +0 -0
  112. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/runner.py +0 -0
  113. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/scaffold.py +0 -0
  114. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/schedule.py +0 -0
  115. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/service_unit.py +0 -0
  116. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/startup_check.py +0 -0
  117. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/agent_runner/vcs_state.py +0 -0
  118. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/build.sh +0 -0
  119. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/deploy/Dockerfile +0 -0
  120. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/deploy/docker-compose.yml +0 -0
  121. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/docs/README.md +0 -0
  122. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/docs/architecture.md +0 -0
  123. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/docs/commands.md +0 -0
  124. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/docs/configuration.md +0 -0
  125. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/docs/events.md +0 -0
  126. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/docs/long-running-agents.md +0 -0
  127. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/docs/memory-efficiency.md +0 -0
  128. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/docs/migrations/0.2.md +0 -0
  129. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/docs/migrations/0.3.md +0 -0
  130. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/docs/quickstart.md +0 -0
  131. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/docs/recipes/aider.md +0 -0
  132. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/docs/recipes/codewhale.md +0 -0
  133. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/docs/recipes/container-pi.md +0 -0
  134. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/docs/recipes/deploy-all-in-one.md +0 -0
  135. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/docs/recipes/kimi.md +0 -0
  136. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/docs/recipes/pi.md +0 -0
  137. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/docs/runbook.md +0 -0
  138. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/docs/thesis.md +0 -0
  139. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/pyproject.toml +0 -0
  140. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/__init__.py +0 -0
  141. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/_clock.py +0 -0
  142. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/_test_helpers.py +0 -0
  143. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/conftest.py +0 -0
  144. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/contract/__init__.py +0 -0
  145. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/contract/test_public_api_surface.py +0 -0
  146. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/e2e/__init__.py +0 -0
  147. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/e2e/conftest.py +0 -0
  148. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/e2e/test_e2e_graceful_stop.py +0 -0
  149. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/e2e/test_e2e_install_systemd.py +0 -0
  150. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/e2e/test_e2e_monitor_remote.py +0 -0
  151. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/e2e/test_e2e_round_lifecycle.py +0 -0
  152. {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
  153. {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
  154. {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
  155. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/generate_vulture_whitelist.py +0 -0
  156. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/integration/__init__.py +0 -0
  157. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/integration/test_auto_stop_e2e.py +0 -0
  158. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/integration/test_bounded_run.py +0 -0
  159. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/integration/test_context_enricher_namespacing.py +0 -0
  160. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/integration/test_dirty_handler_seam.py +0 -0
  161. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/integration/test_fresh_eyes_signal.py +0 -0
  162. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/integration/test_grace_kill_emission.py +0 -0
  163. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/integration/test_install_dry_run.py +0 -0
  164. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/integration/test_monitor_seeded.py +0 -0
  165. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/integration/test_plugin_detector_loaded.py +0 -0
  166. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/integration/test_plugin_owned_paths.py +0 -0
  167. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/integration/test_plugin_real_flow.py +0 -0
  168. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/integration/test_prompt_delivery_stdin.py +0 -0
  169. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/integration/test_run_one_round_with_fake_agent.py +0 -0
  170. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/integration/test_scaffold_presets.py +0 -0
  171. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/integration/test_serve_loop.py +0 -0
  172. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/integration/test_spawn_round_mem_floor.py +0 -0
  173. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/integration/test_spawn_round_wedged.py +0 -0
  174. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/integration/test_substrate_fingerprint.py +0 -0
  175. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/integration/test_transient_error_backoff.py +0 -0
  176. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/__init__.py +0 -0
  177. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/_docs.py +0 -0
  178. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/_event_scan.py +0 -0
  179. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_architecture.py +0 -0
  180. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_atomic_write_enforced.py +0 -0
  181. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_authored_facts_declared.py +0 -0
  182. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_auto_stop_policy_ssot.py +0 -0
  183. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_bdd_test_conventions.py +0 -0
  184. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_builtin_plugin_names_sync.py +0 -0
  185. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_catalogs.py +0 -0
  186. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_classification_ssot.py +0 -0
  187. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_config_error_consistency.py +0 -0
  188. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_config_value_set_ssot.py +0 -0
  189. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_container_stop_bound.py +0 -0
  190. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_dataclass_fields_have_producers.py +0 -0
  191. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_doc_builtin_plugins.py +0 -0
  192. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_doc_claims_match_ssot.py +0 -0
  193. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_doc_cli_claims.py +0 -0
  194. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_doc_operator_surface.py +0 -0
  195. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_doc_test_pointers_exist.py +0 -0
  196. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_doc_transient_error_claims.py +0 -0
  197. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_doc_usage_event_fields.py +0 -0
  198. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_docs_generated.py +0 -0
  199. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_docs_index_complete.py +0 -0
  200. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_entry_points_resolve.py +0 -0
  201. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_event_int_coercion.py +0 -0
  202. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_event_kind_registry.py +0 -0
  203. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_event_kinds_ssot.py +0 -0
  204. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_events_doc_contract.py +0 -0
  205. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_gen_blocks_name_their_source.py +0 -0
  206. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_hook_contract_docs.py +0 -0
  207. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_kill_tests_not_skipped.py +0 -0
  208. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_layer_2_loop_size.py +0 -0
  209. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_migrations_registry_ssot.py +0 -0
  210. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_module_boundaries.py +0 -0
  211. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_module_sizes.py +0 -0
  212. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_monitor_self_exclusion.py +0 -0
  213. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_no_ai_signatures.py +0 -0
  214. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_no_internal_refs.py +0 -0
  215. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_no_price_logic.py +0 -0
  216. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_no_pytest_skip_on_parse_fail.py +0 -0
  217. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_no_raw_time.py +0 -0
  218. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_no_vacuous_invariants.py +0 -0
  219. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_phase_select_stateless.py +0 -0
  220. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_plugins_config_stable.py +0 -0
  221. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_readme_zh_is_pointer.py +0 -0
  222. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_repo_constants_patched_in_tests.py +0 -0
  223. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_round_alloc_growth.py +0 -0
  224. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_round_log_decode_boundary.py +0 -0
  225. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_round_num_single_source.py +0 -0
  226. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_round_result_stable.py +0 -0
  227. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_set_diff_for_auto_tool_classification.py +0 -0
  228. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_stash_uses_sha_not_index.py +0 -0
  229. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_timeout_budget_invariant.py +0 -0
  230. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_upstream_schema_canary.py +0 -0
  231. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/invariants/test_vulture_whitelist_generated.py +0 -0
  232. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/linux/__init__.py +0 -0
  233. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/linux/test_plugin_sandbox_kill.py +0 -0
  234. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/literate/__init__.py +0 -0
  235. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/literate/parser.py +0 -0
  236. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/literate/test_parser.py +0 -0
  237. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/literate/test_quickstart.py +0 -0
  238. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/__init__.py +0 -0
  239. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_agent_runtime.py +0 -0
  240. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_agent_runtime_container.py +0 -0
  241. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_agent_runtime_grace.py +0 -0
  242. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_agent_runtime_marker_scan.py +0 -0
  243. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_agent_runtime_progress.py +0 -0
  244. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_agent_runtime_reap.py +0 -0
  245. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_agent_runtime_signal_name.py +0 -0
  246. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_api_assemble_prompt.py +0 -0
  247. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_api_events_stream.py +0 -0
  248. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_api_install.py +0 -0
  249. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_api_read_round_num.py +0 -0
  250. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_api_resolve_phase.py +0 -0
  251. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_api_service.py +0 -0
  252. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_api_types.py +0 -0
  253. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_auto_stop_gating.py +0 -0
  254. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_builtin_provenance.py +0 -0
  255. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_catalogs.py +0 -0
  256. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_claude_error_detector.py +0 -0
  257. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_claude_foreign_schema.py +0 -0
  258. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_cli.py +0 -0
  259. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_cli_common.py +0 -0
  260. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_cli_init_install.py +0 -0
  261. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_cli_main_boundary.py +0 -0
  262. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_cli_monitor_http.py +0 -0
  263. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_cli_service_peek_monitor.py +0 -0
  264. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_cli_upgrade.py +0 -0
  265. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_codewhale_code_precedence.py +0 -0
  266. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_codewhale_plugin.py +0 -0
  267. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_coerce_int_poison.py +0 -0
  268. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_collapse_spawn_decisions.py +0 -0
  269. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_config.py +0 -0
  270. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_config_fresh_eyes.py +0 -0
  271. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_config_max_rounds.py +0 -0
  272. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_config_nested_strictness.py +0 -0
  273. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_config_prompt_delivery.py +0 -0
  274. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_config_schedule.py +0 -0
  275. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_config_stop_file.py +0 -0
  276. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_config_strictness.py +0 -0
  277. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_config_substrate_fingerprint_paths.py +0 -0
  278. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_config_transient_error_action.py +0 -0
  279. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_context_store.py +0 -0
  280. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_control_char_config.py +0 -0
  281. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_default_dirty_handler.py +0 -0
  282. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_defenses.py +0 -0
  283. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_detect_hung_latch.py +0 -0
  284. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_detector_isolation.py +0 -0
  285. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_detector_protocol.py +0 -0
  286. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_dirty_handlers.py +0 -0
  287. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_dispatch_dirty_owner_branch.py +0 -0
  288. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_docgen.py +0 -0
  289. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_doctor_sandbox.py +0 -0
  290. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_effective_throttle_view.py +0 -0
  291. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_emit_config_migrated.py +0 -0
  292. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_emit_schedule.py +0 -0
  293. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_emit_schedule_phase_skipped.py +0 -0
  294. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_events.py +0 -0
  295. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_events_cmd.py +0 -0
  296. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_events_cmd_rollover.py +0 -0
  297. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_events_cmd_tail.py +0 -0
  298. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_events_jsonl_decode.py +0 -0
  299. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_example_dirty_handler.py +0 -0
  300. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_example_plugin.py +0 -0
  301. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_exec_prefix.py +0 -0
  302. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_exit_cause.py +0 -0
  303. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_exit_classifier.py +0 -0
  304. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_fresh_eyes_trigger.py +0 -0
  305. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_gate_serve_boot.py +0 -0
  306. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_gemini_plugin.py +0 -0
  307. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_git_timeout.py +0 -0
  308. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_hook_failure_isolation.py +0 -0
  309. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_hook_redact_order.py +0 -0
  310. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_hooks.py +0 -0
  311. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_host_health.py +0 -0
  312. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_http_progress.py +0 -0
  313. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_http_progress_epoch.py +0 -0
  314. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_init_entry_points.py +0 -0
  315. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_interruptible_sleep_should_stop.py +0 -0
  316. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_kimi_plugin.py +0 -0
  317. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_lifecycle.py +0 -0
  318. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_load_fail_closed.py +0 -0
  319. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_loader_split.py +0 -0
  320. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_manifest_spawn_hooks.py +0 -0
  321. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_metrics.py +0 -0
  322. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_metrics_cgroup_usage.py +0 -0
  323. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_metrics_swap.py +0 -0
  324. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_migrate_cmd.py +0 -0
  325. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_migrations.py +0 -0
  326. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_monitor_assembly.py +0 -0
  327. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_monitor_cmd_severity.py +0 -0
  328. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_monitor_dedup_identity.py +0 -0
  329. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_monitor_dedup_rearm.py +0 -0
  330. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_monitor_detect_anomaly_repetitive.py +0 -0
  331. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_monitor_detect_rate_limit.py +0 -0
  332. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_monitor_detect_supervisor_stale.py +0 -0
  333. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_monitor_detectors.py +0 -0
  334. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_monitor_event_tail.py +0 -0
  335. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_monitor_loop.py +0 -0
  336. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_monitor_on_alert.py +0 -0
  337. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_monitor_remote.py +0 -0
  338. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_monitor_round_deferred_stale.py +0 -0
  339. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_monitor_schedule_pause.py +0 -0
  340. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_network_blip_signal_guard.py +0 -0
  341. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_open_round_log.py +0 -0
  342. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_orphan_chain_single_pass.py +0 -0
  343. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_outer_round_ceiling.py +0 -0
  344. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_peek_argparse.py +0 -0
  345. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_peek_project_isolation.py +0 -0
  346. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_peek_sandbox_block.py +0 -0
  347. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_peek_schedule.py +0 -0
  348. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_peek_select.py +0 -0
  349. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_phase_agent_launch.py +0 -0
  350. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_phase_profiles.py +0 -0
  351. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_phase_select.py +0 -0
  352. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_pi_plugin.py +0 -0
  353. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_plugin_checksum.py +0 -0
  354. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_plugin_constants.py +0 -0
  355. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_plugin_name_mismatch.py +0 -0
  356. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_plugin_sandbox_wire.py +0 -0
  357. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_plugin_scan_parity.py +0 -0
  358. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_plugins_config_fields.py +0 -0
  359. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_presets.py +0 -0
  360. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_primary_prompt_file_home.py +0 -0
  361. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_prompt_loader.py +0 -0
  362. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_read_json_hardening.py +0 -0
  363. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_redact.py +0 -0
  364. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_resolve.py +0 -0
  365. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_round_cmd.py +0 -0
  366. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_round_cmd_sigterm.py +0 -0
  367. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_round_log_helpers.py +0 -0
  368. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_round_outcome.py +0 -0
  369. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_round_outcome_agent_axis.py +0 -0
  370. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_round_view.py +0 -0
  371. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_runner.py +0 -0
  372. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_runner_sidecar_ordering.py +0 -0
  373. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_runner_throttle.py +0 -0
  374. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_sandbox_probe.py +0 -0
  375. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_scaffold.py +0 -0
  376. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_schedule.py +0 -0
  377. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_serve_cmd_bounded.py +0 -0
  378. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_serve_config_broken.py +0 -0
  379. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_serve_crash_loop.py +0 -0
  380. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_serve_mem_gate.py +0 -0
  381. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_serve_phase_schedule.py +0 -0
  382. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_serve_policy.py +0 -0
  383. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_serve_round.py +0 -0
  384. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_serve_round_cgroup_spine.py +0 -0
  385. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_serve_round_log.py +0 -0
  386. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_serve_round_oom_killed.py +0 -0
  387. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_serve_round_terminate.py +0 -0
  388. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_serve_schedule_gate.py +0 -0
  389. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_serve_sentinel.py +0 -0
  390. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_serve_startup_hooks.py +0 -0
  391. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_service_mode.py +0 -0
  392. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_service_unit.py +0 -0
  393. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_spawn_seam.py +0 -0
  394. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_startup_battery_exit.py +0 -0
  395. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_startup_check.py +0 -0
  396. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_substrate.py +0 -0
  397. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_supervisor_stale_self_blind.py +0 -0
  398. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_throttle_back_off_ladder.py +0 -0
  399. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_throttle_epoch_bound.py +0 -0
  400. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_throttle_plugin_classification.py +0 -0
  401. {cli_agent_runner-0.3.2 → cli_agent_runner-0.3.3}/tests/unit/test_upgrade_migrate.py +0 -0
  402. {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.2
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.2'
22
- __version_tuple__ = version_tuple = (0, 3, 2)
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(name="gemini", post_round_hooks=(GeminiErrorDetector(),))
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.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.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.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 task
55
- # queue", "process group", "a watertight seam" -- never matches: "Group
56
- # Alpha" fails because `\b` cannot land between the two word characters "A"
57
- # and "l", and a bare "task"/"seam" with no following digit never matches at
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", and "seam" used as an ordinary noun with no
162
- following digit."""
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
  ]
@@ -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.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)