cli-agent-runner 0.3.7__tar.gz → 0.3.9__tar.gz

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