cli-agent-runner 0.2.8__tar.gz → 0.2.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 (280) hide show
  1. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/.vulture-whitelist.py +18 -0
  2. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/CHANGELOG.md +25 -48
  3. cli_agent_runner-0.2.9/CONTRIBUTING.md +120 -0
  4. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/PKG-INFO +7 -14
  5. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/README.md +6 -13
  6. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/_docgen.py +48 -9
  7. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/_emit.py +24 -5
  8. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/_version.py +2 -2
  9. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/api.py +9 -21
  10. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/cli/serve_cmd.py +132 -32
  11. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/config.py +167 -33
  12. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/events.py +1 -0
  13. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/migrations.py +26 -0
  14. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/monitor.py +1 -0
  15. cli_agent_runner-0.2.9/agent_runner/phase_select.py +106 -0
  16. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/runner.py +11 -9
  17. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/startup_check.py +34 -13
  18. cli_agent_runner-0.2.9/docs/README.md +45 -0
  19. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/docs/architecture.md +8 -17
  20. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/docs/commands.md +23 -17
  21. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/docs/configuration.md +131 -36
  22. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/docs/long-running-agents.md +27 -84
  23. cli_agent_runner-0.2.9/docs/migrations/0.2.md +135 -0
  24. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/docs/plugins.md +69 -230
  25. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/docs/recipes/aider.md +4 -2
  26. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/docs/recipes/codewhale.md +1 -0
  27. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/docs/runbook.md +71 -7
  28. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/docs/thesis.md +1 -1
  29. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/pyproject.toml +5 -0
  30. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/integration/test_context_enricher_namespacing.py +9 -1
  31. cli_agent_runner-0.2.9/tests/invariants/_docs.py +18 -0
  32. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/invariants/test_architecture.py +2 -1
  33. cli_agent_runner-0.2.9/tests/invariants/test_authored_facts_declared.py +77 -0
  34. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/invariants/test_config_error_consistency.py +4 -3
  35. cli_agent_runner-0.2.9/tests/invariants/test_doc_test_pointers_exist.py +22 -0
  36. cli_agent_runner-0.2.9/tests/invariants/test_doc_usage_event_fields.py +32 -0
  37. cli_agent_runner-0.2.9/tests/invariants/test_gen_blocks_name_their_source.py +28 -0
  38. cli_agent_runner-0.2.9/tests/invariants/test_phase_select_stateless.py +50 -0
  39. cli_agent_runner-0.2.9/tests/unit/test_emit_schedule_phase_skipped.py +39 -0
  40. cli_agent_runner-0.2.9/tests/unit/test_example_dirty_handler.py +46 -0
  41. cli_agent_runner-0.2.9/tests/unit/test_example_plugin.py +65 -0
  42. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_migrations.py +24 -0
  43. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_peek_schedule.py +14 -0
  44. cli_agent_runner-0.2.9/tests/unit/test_phase_agent_launch.py +110 -0
  45. cli_agent_runner-0.2.9/tests/unit/test_phase_profiles.py +120 -0
  46. cli_agent_runner-0.2.9/tests/unit/test_phase_select.py +140 -0
  47. cli_agent_runner-0.2.9/tests/unit/test_serve_phase_schedule.py +193 -0
  48. cli_agent_runner-0.2.8/CONTRIBUTING.md +0 -83
  49. cli_agent_runner-0.2.8/docs/README.md +0 -40
  50. cli_agent_runner-0.2.8/docs/migrations/0.1.28.md +0 -176
  51. cli_agent_runner-0.2.8/docs/migrations/0.2.0.md +0 -165
  52. cli_agent_runner-0.2.8/docs/migrations/0.2.1.md +0 -77
  53. cli_agent_runner-0.2.8/docs/migrations/0.2.2.md +0 -242
  54. cli_agent_runner-0.2.8/docs/migrations/0.2.3.md +0 -44
  55. cli_agent_runner-0.2.8/docs/migrations/0.2.4.md +0 -66
  56. cli_agent_runner-0.2.8/docs/migrations/0.2.5.md +0 -99
  57. cli_agent_runner-0.2.8/docs/migrations/0.2.6.md +0 -127
  58. cli_agent_runner-0.2.8/docs/migrations/0.2.7.md +0 -121
  59. cli_agent_runner-0.2.8/docs/migrations/0.2.8.md +0 -79
  60. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/.codecov.yml +0 -0
  61. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  62. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  63. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  64. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  65. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/.github/workflows/ci.yml +0 -0
  66. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/.github/workflows/release.yml +0 -0
  67. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/.gitignore +0 -0
  68. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/BACKLOG.md +0 -0
  69. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/CODE_OF_CONDUCT.md +0 -0
  70. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/LICENSE +0 -0
  71. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/README.zh.md +0 -0
  72. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/SECURITY.md +0 -0
  73. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/__init__.py +0 -0
  74. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/_redact.py +0 -0
  75. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/_registry.py +0 -0
  76. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/_substrate.py +0 -0
  77. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/_throttle.py +0 -0
  78. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/agent_runtime.py +0 -0
  79. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/api_types.py +0 -0
  80. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/builtin_plugins/__init__.py +0 -0
  81. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/builtin_plugins/_constants.py +0 -0
  82. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/builtin_plugins/claude_rate_limit.py +0 -0
  83. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/builtin_plugins/codewhale.py +0 -0
  84. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/builtin_plugins/default_dirty_handler.py +0 -0
  85. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/builtin_plugins/gemini.py +0 -0
  86. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/builtin_plugins/kimi.py +0 -0
  87. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/builtin_plugins/pi.py +0 -0
  88. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/cli/__init__.py +0 -0
  89. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/cli/__main__.py +0 -0
  90. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/cli/common.py +0 -0
  91. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/cli/events_cmd.py +0 -0
  92. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/cli/init_cmd.py +0 -0
  93. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/cli/install_cmd.py +0 -0
  94. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/cli/migrate_cmd.py +0 -0
  95. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/cli/monitor_cmd.py +0 -0
  96. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/cli/peek_cmd.py +0 -0
  97. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/cli/round_cmd.py +0 -0
  98. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/cli/service_cmd.py +0 -0
  99. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/cli/upgrade_cmd.py +0 -0
  100. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/context_store.py +0 -0
  101. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/defenses.py +0 -0
  102. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/hooks.py +0 -0
  103. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/http_progress.py +0 -0
  104. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/lifecycle.py +0 -0
  105. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/metrics.py +0 -0
  106. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/presets/__init__.py +0 -0
  107. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/presets/aider.toml +0 -0
  108. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/presets/claude.toml +0 -0
  109. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/presets/codewhale.toml +0 -0
  110. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/presets/gemini.toml +0 -0
  111. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/presets/kimi.toml +0 -0
  112. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/presets/pi.toml +0 -0
  113. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/prompt_loader.py +0 -0
  114. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/remote_relay.py +0 -0
  115. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/round_log.py +0 -0
  116. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/round_view.py +0 -0
  117. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/scaffold.py +0 -0
  118. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/schedule.py +0 -0
  119. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/service_unit.py +0 -0
  120. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/agent_runner/vcs_state.py +0 -0
  121. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/build.sh +0 -0
  122. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/docs/events.md +0 -0
  123. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/docs/quickstart.md +0 -0
  124. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/docs/recipes/kimi.md +0 -0
  125. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/docs/recipes/pi.md +0 -0
  126. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/__init__.py +0 -0
  127. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/_test_helpers.py +0 -0
  128. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/conftest.py +0 -0
  129. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/contract/__init__.py +0 -0
  130. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/contract/test_public_api_surface.py +0 -0
  131. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/e2e/__init__.py +0 -0
  132. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/e2e/conftest.py +0 -0
  133. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/e2e/test_e2e_graceful_stop.py +0 -0
  134. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/e2e/test_e2e_install_systemd.py +0 -0
  135. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/e2e/test_e2e_monitor_remote.py +0 -0
  136. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/e2e/test_e2e_round_lifecycle.py +0 -0
  137. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/fixtures/cli-real-output/claude-2.1.143-assistant-tool-use.jsonl +0 -0
  138. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/fixtures/cli-real-output/claude-2.1.143-result-event.jsonl +0 -0
  139. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/fixtures/cli-real-output/gemini-0.42.0-result-event.jsonl +0 -0
  140. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/generate_vulture_whitelist.py +0 -0
  141. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/integration/__init__.py +0 -0
  142. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/integration/test_bounded_run.py +0 -0
  143. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/integration/test_dirty_handler_seam.py +0 -0
  144. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/integration/test_fresh_eyes_signal.py +0 -0
  145. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/integration/test_grace_kill_emission.py +0 -0
  146. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/integration/test_install_dry_run.py +0 -0
  147. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/integration/test_monitor_seeded.py +0 -0
  148. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/integration/test_plugin_detector_loaded.py +0 -0
  149. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/integration/test_plugin_owned_paths.py +0 -0
  150. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/integration/test_plugin_real_flow.py +0 -0
  151. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/integration/test_prompt_delivery_stdin.py +0 -0
  152. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/integration/test_run_one_round_with_fake_agent.py +0 -0
  153. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/integration/test_scaffold_presets.py +0 -0
  154. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/integration/test_serve_loop.py +0 -0
  155. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/integration/test_substrate_fingerprint.py +0 -0
  156. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/integration/test_transient_error_backoff.py +0 -0
  157. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/invariants/__init__.py +0 -0
  158. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/invariants/_event_scan.py +0 -0
  159. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/invariants/test_atomic_write_enforced.py +0 -0
  160. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/invariants/test_auto_stop_policy_ssot.py +0 -0
  161. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/invariants/test_catalogs.py +0 -0
  162. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/invariants/test_classification_ssot.py +0 -0
  163. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/invariants/test_config_value_set_ssot.py +0 -0
  164. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/invariants/test_doc_builtin_plugins.py +0 -0
  165. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/invariants/test_doc_claims_match_ssot.py +0 -0
  166. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/invariants/test_doc_cli_claims.py +0 -0
  167. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/invariants/test_doc_operator_surface.py +0 -0
  168. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/invariants/test_doc_transient_error_claims.py +0 -0
  169. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/invariants/test_docs_generated.py +0 -0
  170. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/invariants/test_docs_index_complete.py +0 -0
  171. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/invariants/test_entry_points_resolve.py +0 -0
  172. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/invariants/test_event_kind_registry.py +0 -0
  173. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/invariants/test_event_kinds_ssot.py +0 -0
  174. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/invariants/test_events_doc_contract.py +0 -0
  175. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/invariants/test_hook_contract_docs.py +0 -0
  176. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/invariants/test_layer_2_loop_size.py +0 -0
  177. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/invariants/test_module_boundaries.py +0 -0
  178. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/invariants/test_module_sizes.py +0 -0
  179. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/invariants/test_no_ai_signatures.py +0 -0
  180. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/invariants/test_no_pytest_skip_on_parse_fail.py +0 -0
  181. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/invariants/test_peek_schema_version.py +0 -0
  182. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/invariants/test_plugins_config_stable.py +0 -0
  183. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/invariants/test_readme_zh_is_pointer.py +0 -0
  184. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/invariants/test_repo_constants_patched_in_tests.py +0 -0
  185. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/invariants/test_round_result_stable.py +0 -0
  186. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/invariants/test_set_diff_for_auto_tool_classification.py +0 -0
  187. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/invariants/test_stash_uses_sha_not_index.py +0 -0
  188. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/invariants/test_upstream_schema_canary.py +0 -0
  189. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/invariants/test_vulture_whitelist_generated.py +0 -0
  190. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/literate/__init__.py +0 -0
  191. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/literate/parser.py +0 -0
  192. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/literate/test_parser.py +0 -0
  193. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/literate/test_quickstart.py +0 -0
  194. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/__init__.py +0 -0
  195. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_agent_runtime.py +0 -0
  196. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_agent_runtime_grace.py +0 -0
  197. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_agent_runtime_progress.py +0 -0
  198. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_agent_runtime_signal_name.py +0 -0
  199. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_api_assemble_prompt.py +0 -0
  200. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_api_events_stream.py +0 -0
  201. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_api_install.py +0 -0
  202. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_api_observation.py +0 -0
  203. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_api_read_round_num.py +0 -0
  204. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_api_resolve_phase.py +0 -0
  205. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_api_service.py +0 -0
  206. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_api_types.py +0 -0
  207. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_auto_stop_gating.py +0 -0
  208. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_catalogs.py +0 -0
  209. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_claude_error_detector.py +0 -0
  210. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_cli.py +0 -0
  211. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_cli_common.py +0 -0
  212. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_cli_init_install.py +0 -0
  213. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_cli_monitor_http.py +0 -0
  214. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_cli_service_peek_monitor.py +0 -0
  215. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_cli_upgrade.py +0 -0
  216. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_codewhale_plugin.py +0 -0
  217. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_config.py +0 -0
  218. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_config_fresh_eyes.py +0 -0
  219. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_config_max_rounds.py +0 -0
  220. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_config_prompt_delivery.py +0 -0
  221. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_config_schedule.py +0 -0
  222. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_config_stop_file.py +0 -0
  223. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_config_substrate_fingerprint_paths.py +0 -0
  224. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_config_transient_error_action.py +0 -0
  225. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_context_store.py +0 -0
  226. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_default_dirty_handler.py +0 -0
  227. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_defenses.py +0 -0
  228. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_detector_protocol.py +0 -0
  229. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_dirty_handlers.py +0 -0
  230. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_docgen.py +0 -0
  231. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_emit_config_migrated.py +0 -0
  232. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_emit_schedule.py +0 -0
  233. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_events.py +0 -0
  234. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_events_cmd.py +0 -0
  235. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_events_cmd_tail.py +0 -0
  236. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_exit_cause.py +0 -0
  237. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_fresh_eyes_trigger.py +0 -0
  238. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_gemini_plugin.py +0 -0
  239. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_hook_failure_isolation.py +0 -0
  240. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_hooks.py +0 -0
  241. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_http_progress.py +0 -0
  242. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_init_entry_points.py +0 -0
  243. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_kimi_plugin.py +0 -0
  244. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_lifecycle.py +0 -0
  245. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_metrics.py +0 -0
  246. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_migrate_cmd.py +0 -0
  247. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_monitor_assembly.py +0 -0
  248. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_monitor_detect_anomaly_repetitive.py +0 -0
  249. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_monitor_detect_rate_limit.py +0 -0
  250. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_monitor_detect_supervisor_stale.py +0 -0
  251. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_monitor_detectors.py +0 -0
  252. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_monitor_remote.py +0 -0
  253. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_monitor_schedule_pause.py +0 -0
  254. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_network_blip_signal_guard.py +0 -0
  255. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_peek_argparse.py +0 -0
  256. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_peek_select.py +0 -0
  257. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_pi_plugin.py +0 -0
  258. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_plugin_constants.py +0 -0
  259. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_presets.py +0 -0
  260. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_prompt_loader.py +0 -0
  261. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_redact.py +0 -0
  262. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_round_log_helpers.py +0 -0
  263. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_round_view.py +0 -0
  264. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_runner.py +0 -0
  265. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_runner_throttle.py +0 -0
  266. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_scaffold.py +0 -0
  267. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_schedule.py +0 -0
  268. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_serve_cmd_bounded.py +0 -0
  269. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_serve_config_broken.py +0 -0
  270. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_serve_crash_loop.py +0 -0
  271. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_serve_round_log.py +0 -0
  272. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_serve_schedule_gate.py +0 -0
  273. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_serve_sentinel.py +0 -0
  274. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_serve_startup_hooks.py +0 -0
  275. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_service_unit.py +0 -0
  276. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_startup_check.py +0 -0
  277. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_substrate.py +0 -0
  278. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_throttle_plugin_classification.py +0 -0
  279. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_upgrade_migrate.py +0 -0
  280. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.9}/tests/unit/test_vcs_state.py +0 -0
@@ -144,15 +144,24 @@ disk_critical_pct
144
144
  round_timeout_s
145
145
  disable_pre_round_hooks
146
146
  prompt_files
147
+ agent
148
+ schedule
147
149
 
148
150
  # agent_runner.config.PhasesConfig
149
151
  list
150
152
  overrides
153
+ phase_policy
151
154
 
152
155
  # agent_runner.config.PluginsConfig
153
156
  disable
154
157
  raw
155
158
 
159
+ # agent_runner.config.Profile
160
+ agent
161
+ runtime
162
+ schedule
163
+ prompt_files
164
+
156
165
  # agent_runner.config.PromptConfig
157
166
  file
158
167
  files
@@ -245,6 +254,15 @@ manual
245
254
  # agent_runner.monitor.LocalSource
246
255
  log_dir
247
256
 
257
+ # agent_runner.phase_select.Selection
258
+ phase
259
+ paused
260
+ resume_at
261
+ resume_phase
262
+ resume_timezone
263
+ skipped
264
+ active_window
265
+
248
266
  # agent_runner.round_log.PruneOutcome
249
267
  deleted
250
268
  deferred
@@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.2.9] - 2026-08-28
9
+
10
+ ### Added
11
+ - Per-phase profiles: `[phases.<name>.agent]` and `[phases.<name>.schedule]` join the existing runtime/prompt overrides, so each phase resolves its own `(agent, runtime, schedule, prompt files)`. A phase's `[...agent]` field-merges onto the base `[agent]` (swap just `command`, inherit the rest); its `[...schedule]` replaces the global windows wholesale. Runs each phase under its own model — see the mixed-model rotation recipe.
12
+ - `[phases.<name>.runtime]` nested sub-table for `round_timeout_s` / `disable_pre_round_hooks`; the flat `[phases.<name>]` form stays as a permanent alias. Setting both twins is a config error.
13
+ - `[phases] phase_policy` (`wait` | `skip`): on a per-phase schedule, `wait` idle-sleeps until this round's phase opens; `skip` steps the rotation forward to the first open phase and runs it. `schedule_phase_skipped` event (`round_num`, `skipped`, `chosen`, `active_window`) records the stepped-over phases.
14
+ - `agent-runner migrate` reports (does not rewrite) flat per-phase runtime overrides that can move under `[phases.<name>.runtime]`.
15
+
16
+ See `docs/migrations/0.2.md`.
17
+
8
18
  ## [0.2.8] - 2026-08-25
9
19
 
10
20
  ### Added
@@ -14,7 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
14
24
  ### Changed
15
25
  - Removed-field `ConfigError` messages now point to `agent-runner migrate`.
16
26
 
17
- See `docs/migrations/0.2.8.md`.
27
+ See `docs/migrations/0.2.md`.
18
28
 
19
29
  ## [0.2.7] - 2026-08-25
20
30
 
@@ -26,7 +36,7 @@ See `docs/migrations/0.2.8.md`.
26
36
  ### Fixed
27
37
  - Monitor no longer raises `supervisor_stale` during an intentional schedule pause (suppressed until `resume_at` plus one staleness window).
28
38
 
29
- See `docs/migrations/0.2.7.md`.
39
+ See `docs/migrations/0.2.md`.
30
40
 
31
41
  ## [0.2.6] - 2026-07-28
32
42
 
@@ -39,7 +49,7 @@ See `docs/migrations/0.2.7.md`.
39
49
  ### Added
40
50
  - `round_logs_prune_deferred` event — emitted on every prune attempt the bulk guard defers, carrying `directory`, `existing`, `keep`, `would_delete` and a hint naming `runtime.round_log_retention`. Resolve by raising retention above the backlog or deleting the files yourself; the guard never blocks a round. Retention `0` emits nothing.
41
51
 
42
- See `docs/migrations/0.2.6.md`.
52
+ See `docs/migrations/0.2.md`.
43
53
 
44
54
  ## [0.2.5] - 2026-07-27
45
55
 
@@ -50,7 +60,7 @@ See `docs/migrations/0.2.6.md`.
50
60
  ### Removed
51
61
  - The polling remote monitor (`RemoteSource`, `run_remote_command`, `MonitorRemoteError`, auto-stop over ssh) — it read remote paths on the local filesystem and was already failing loud since 0.2.4. Detection is on-host by design; remote observation is the relay above. `monitor.on_alert` lost its `host` parameter and `monitor_auto_stop_triggered` its `host` field; `monitor_auto_stop_failed` now reports a failed *local* stop (previously a failed ssh stop) instead of crashing the monitor loop.
52
62
 
53
- See `docs/migrations/0.2.5.md`.
63
+ See `docs/migrations/0.2.md`.
54
64
 
55
65
  ## [0.2.4] - 2026-07-27
56
66
 
@@ -67,7 +77,7 @@ See `docs/migrations/0.2.5.md`.
67
77
  - Startup validation resolves the agent command exactly as the spawn does (child's PATH — `[agent.env]` may override it — and `work_dir` base); `PWD` now stays pinned to `work_dir` even if `[agent.env]` sets it. The stdout+stderr merge is now pinned by a behavioral test, not just prose.
68
78
  - Generated serve systemd units now set `KillMode=mixed`: with systemd's default `control-group`, `systemctl stop` SIGTERMed the whole cgroup — agent child included — making the graceful round drain structurally ineffective. Existing installs: re-run `agent-runner install` (or add a drop-in) to pick this up.
69
79
 
70
- See `docs/migrations/0.2.4.md`.
80
+ See `docs/migrations/0.2.md`.
71
81
 
72
82
  ## [0.2.3] - 2026-07-26
73
83
 
@@ -79,7 +89,7 @@ See `docs/migrations/0.2.4.md`.
79
89
  - The agent subprocess now runs in `runtime.work_dir` (`cwd=` on spawn). Previously it inherited the supervisor's cwd and only launch conventions (systemd `WorkingDirectory=`, relative `--config`) kept the two aligned — fatal for agent CLIs with no working-directory flag of their own (e.g. `pi`). The startup check now also validates a relative `agent.command[0]` against `work_dir`, matching where it executes.
80
90
  - Plugin round-log tail window widened 50 → 200 lines: a stderr burst after the agent's terminal JSONL event could evict it from the scan window, silently dropping usage/transient classification. The round log's merged stdout+stderr contract is now documented (`HookContext.agent_log_path`, `docs/long-running-agents.md`) — the merge is deliberate; auth/network detection reads stderr text from it.
81
91
 
82
- See `docs/migrations/0.2.3.md`.
92
+ See `docs/migrations/0.2.md`.
83
93
 
84
94
  ## [0.2.2] - 2026-07-18
85
95
 
@@ -102,7 +112,7 @@ See `docs/migrations/0.2.3.md`.
102
112
  ### Added
103
113
  - Housekeeping: the build gate runs `vulture` (dead-code scan, whitelist auto-generated from `@dataclass` fields); `AGENT_RUNNER_FRESH_EYES` is now a documented, tested round-subprocess env-var contract; `SECURITY.md` gains a threat model (agent-runner is a supervisor, not a sandbox).
104
114
 
105
- See `docs/migrations/0.2.2.md`.
115
+ See `docs/migrations/0.2.md`.
106
116
 
107
117
  ## [0.2.1] - 2026-07-16
108
118
 
@@ -113,7 +123,7 @@ See `docs/migrations/0.2.2.md`.
113
123
  ### Fixed
114
124
  - A signal-killed round is no longer misclassified as `agent_network_blip` when its log happens to contain a network-error string; signal deaths are terminations, not network blips.
115
125
 
116
- See `docs/migrations/0.2.1.md`.
126
+ See `docs/migrations/0.2.md`.
117
127
 
118
128
  ## [0.2.0] - 2026-07-02
119
129
 
@@ -121,7 +131,7 @@ See `docs/migrations/0.2.1.md`.
121
131
  - Dirty-tree handling is now pluggable. The clean-exit-dirty policy moved out of core into a `dirty_handler` hook; `stash` / `ignore` / `auto_commit` now ship as the bundled, default-on `default_dirty_handler` plugin. **No behavior or config change for existing users** — `[vcs] dirty_action` works exactly as before.
122
132
 
123
133
  ### Added
124
- - `dirty_handler` plugin seam (4th lifecycle hook) + `DirtyOutcome` on `RoundResult`; `stash_orphan` / `try_auto_commit` are now public `api` primitives. Consumers can fully own dirty-tree policy — see `docs/migrations/0.2.0.md`.
134
+ - `dirty_handler` plugin seam (4th lifecycle hook) + `DirtyOutcome` on `RoundResult`; `stash_orphan` / `try_auto_commit` are now public `api` primitives. Consumers can fully own dirty-tree policy — see `docs/migrations/0.2.md`.
125
135
  - `dirty_auto_committed` event (emitted when a handler auto-commits).
126
136
 
127
137
  ## [0.1.42] - 2026-06-25
@@ -150,7 +160,7 @@ See `docs/migrations/0.2.1.md`.
150
160
  ### Security
151
161
  - Grace-kill child-process fields (`live_children` / `ignored_children` in `round_grace_extended` / `round_grace_kill`) no longer store raw command lines — only the executable basename + pid (and, for ignored children, which ignore-pattern matched). This structurally prevents secrets passed in a child's arguments from reaching `events-*.jsonl`. The field shape changed from a list of strings to a list of objects.
152
162
  - Free-text event excerpts that can carry agent output — `transient_error_detected.raw`, `hook_failed.error_message`/`traceback`, `serve_startup_hook_failed.exc_msg` — are now best-effort redacted (auth headers, tokens, credential URLs, `KEY=value` secrets, known key-prefixes, JWT, PEM).
153
- - Pre-0.1.40 `events-*.jsonl` may contain unredacted argv/excerpts — see `docs/migrations/0.1.40.md`.
163
+ - Pre-0.1.40 `events-*.jsonl` may contain unredacted argv/excerpts.
154
164
 
155
165
  ### Changed
156
166
  - Docs: `configuration.md` `[monitor.host_health]` example points to the generated schema table instead of restating default values.
@@ -206,7 +216,7 @@ See `docs/migrations/0.2.1.md`.
206
216
  ## [0.1.35] - 2026-05-20
207
217
 
208
218
  ### Removed
209
- - `claude_rate_limit_detector` plugin alias (0.1.20-era back-compat layer after the 0.1.23 rename to `claude_error_detector`). Hard-cut at both entry-point and config-mapping layers. See `docs/migrations/0.1.35.md` for the 1-line TOML migration.
219
+ - `claude_rate_limit_detector` plugin alias (0.1.20-era back-compat layer after the 0.1.23 rename to `claude_error_detector`). Hard-cut at both entry-point and config-mapping layers.
210
220
 
211
221
  ## [0.1.34] - 2026-05-20
212
222
 
@@ -218,8 +228,6 @@ See `docs/migrations/0.2.1.md`.
218
228
  ### Removed
219
229
  - `peek --select events.<kind>` selector (mis-placed in state-snapshot verb). Use `events --kind <kind>` instead. 1-line `s///` migration.
220
230
 
221
- See `docs/migrations/0.1.34.md`.
222
-
223
231
  ## [0.1.33] - 2026-05-19
224
232
 
225
233
  ### Added
@@ -228,8 +236,6 @@ See `docs/migrations/0.1.34.md`.
228
236
  - `transient_error_backoff_capped` event gains `original_reset_at_epoch`, `applied_reset_at_epoch`, `consecutive_count`, `capped_by_absolute_max` fields for backoff-curve observability.
229
237
  - `docs/thesis.md` names the server-authoritative vs estimated reset principle.
230
238
 
231
- See `docs/migrations/0.1.33.md`.
232
-
233
239
  ## [0.1.32] - 2026-05-18
234
240
 
235
241
  ### Added
@@ -238,8 +244,6 @@ See `docs/migrations/0.1.33.md`.
238
244
  - `[monitor.host_health]` config section — `mem_avail_min_mb` / `disk_warning_pct` / `disk_critical_pct` thresholds for `mem_pressure` / `disk_warning` / `disk_critical` detectors. Defaults preserve prior behavior.
239
245
  - New monitor detector `anomaly_repetitive_active` (notify) — alerts when `anomaly_repetitive_tool` events fire in recent rounds. Detector count 10 → 11.
240
246
 
241
- See `docs/migrations/0.1.32.md`.
242
-
243
247
  ## [0.1.31] - 2026-05-18
244
248
 
245
249
  ### Added
@@ -248,8 +252,6 @@ See `docs/migrations/0.1.32.md`.
248
252
  - `[runtime] dry_run` boolean exposed via `HookContext.dry_run` for plugin authors to skip side-effect actions when set.
249
253
  - Documentation: TOML changes require daemon restart (no hot-reload); phase rotation indexing clarification.
250
254
 
251
- See `docs/migrations/0.1.31.md`.
252
-
253
255
  ## [0.1.30] - 2026-05-18
254
256
 
255
257
  ### Fixed
@@ -262,8 +264,6 @@ See `docs/migrations/0.1.31.md`.
262
264
  - `docs/thesis.md` — project non-goals SSOT for feature-request evaluation.
263
265
  - README + runbook callouts for SSH trust boundary of `monitor --host`.
264
266
 
265
- See `docs/migrations/0.1.30.md`.
266
-
267
267
  ## [0.1.29] - 2026-05-17
268
268
 
269
269
  ### Added
@@ -278,8 +278,6 @@ See `docs/migrations/0.1.30.md`.
278
278
  - Legacy API exports: `emit_rate_limit_rejected`, `emit_rate_limit_recovered`, `emit_rate_limit_backoff_capped`.
279
279
  - Config alias `runtime.rate_limit_action` — use `runtime.transient_error_action`. Removed configs now error with migration hint.
280
280
 
281
- See `docs/migrations/0.1.29.md`.
282
-
283
281
  ## [0.1.28] - 2026-05-17
284
282
 
285
283
  ### Added
@@ -295,7 +293,7 @@ See `docs/migrations/0.1.29.md`.
295
293
  - `agent_runner.api_types.ThrottleState` dead alias (0.1.23 back-compat; deprecation window
296
294
  passed; switch to `TransientErrorState`).
297
295
 
298
- See `docs/migrations/0.1.28.md`.
296
+ See `docs/plugins.md` under `claude_error_detector` for the `agent_usage_recorded` payload schema.
299
297
 
300
298
  ## [0.1.27] - 2026-05-17
301
299
 
@@ -305,11 +303,9 @@ See `docs/migrations/0.1.28.md`.
305
303
  Affects supervisors consuming transient_error_detected.
306
304
 
307
305
  ### Added
308
- - docs/migrations/0.1.27.md: supervisor usage guide for transient_error_detected event
306
+ - Supervisor usage guide for transient_error_detected event
309
307
  (4-bucket dispatch table + back-off recipe).
310
308
 
311
- See `docs/migrations/0.1.27.md`.
312
-
313
309
  ## [0.1.26] - 2026-05-17
314
310
 
315
311
  - Fix claude `agent_usage_recorded` `model` field (was always
@@ -322,8 +318,6 @@ See `docs/migrations/0.1.27.md`.
322
318
  `gemini_error_detector` plugin can parse output. Existing scaffolds
323
319
  need manual TOML edit; round log format changes (text → JSONL).
324
320
 
325
- See `docs/migrations/0.1.26.md`.
326
-
327
321
  ## [0.1.25] - 2026-05-17
328
322
 
329
323
  - **Hotfix**: built-in `claude_error_detector` and `gemini_error_detector`
@@ -334,8 +328,6 @@ See `docs/migrations/0.1.26.md`.
334
328
  - `HookContext.agent_log_path: Path | None = None` (additive). 3rd-party
335
329
  plugin authors reading `ctx.log_dir / "round-{N}.log"` should migrate.
336
330
 
337
- See `docs/migrations/0.1.25.md`.
338
-
339
331
  ## [0.1.24] - 2026-05-17
340
332
 
341
333
  - New `agent_usage_recorded` event: per-round token + cost data, emitted
@@ -348,8 +340,6 @@ See `docs/migrations/0.1.25.md`.
348
340
  unattended operation (gemini CLI refuses headless runs in untrusted
349
341
  dirs). Existing scaffolds need manual edit.
350
342
 
351
- See `docs/migrations/0.1.24.md`.
352
-
353
343
  ## [0.1.23] - 2026-05-17
354
344
 
355
345
  - Generalized claude error handling: new `transient_error_*` event family
@@ -362,8 +352,6 @@ See `docs/migrations/0.1.24.md`.
362
352
  - Plugin `claude_rate_limit_detector` renamed to `claude_error_detector`
363
353
  (entry-point alias preserved).
364
354
 
365
- See `docs/migrations/0.1.23.md`.
366
-
367
355
  ## [0.1.22] - 2026-05-16
368
356
 
369
357
  - `[runtime] substrate_fingerprint_paths` + `round_substrate_before` /
@@ -376,8 +364,6 @@ See `docs/migrations/0.1.23.md`.
376
364
  - New `docs/long-running-agents.md`: hazards + 4 primitives + framework
377
365
  abstraction boundary.
378
366
 
379
- See `docs/migrations/0.1.22.md`.
380
-
381
367
  ## [0.1.21] - 2026-05-16
382
368
 
383
369
  - `[runtime] max_rounds = N` + `--max-rounds N` CLI flag: supervisor
@@ -388,8 +374,6 @@ See `docs/migrations/0.1.22.md`.
388
374
  `systemctl start` to resume.
389
375
  - 2 new events: `max_rounds_reached`, `stop_file_detected`.
390
376
 
391
- See `docs/migrations/0.1.21.md`.
392
-
393
377
  ## [0.1.20] - 2026-05-16
394
378
 
395
379
  - Built-in detection of claude rate-limit rejections (5h OAuth quota).
@@ -402,8 +386,6 @@ See `docs/migrations/0.1.21.md`.
402
386
  - `peek --json` schema bumped 1.8 → 1.9 (additive `rate_limit` field).
403
387
  - New monitor detector `rate_limit_active` (warning, no auto-stop).
404
388
 
405
- See `docs/migrations/0.1.20.md`.
406
-
407
389
  ## [0.1.19] - 2026-05-15
408
390
 
409
391
  - `agent-runner install` derives `ExecStart` via `shutil.which`; fixes
@@ -415,15 +397,12 @@ See `docs/migrations/0.1.20.md`.
415
397
  - New `gemini` preset: `agent-runner init --preset gemini` scaffolds
416
398
  for Gemini CLI (uses `--yolo` for unattended operation).
417
399
 
418
- See `docs/migrations/0.1.19.md`.
419
-
420
400
  ## [0.1.18] - 2026-05-15
421
401
 
422
402
  ### ⚠️ Breaking
423
403
 
424
404
  - `vcs.orphan_action` removed (deprecated in 0.1.17). TOML using the
425
405
  old key raises `ValueError` with migration hint. Use `vcs.dirty_action`.
426
- See `docs/migrations/0.1.17.md`.
427
406
 
428
407
  ## [0.1.17] - 2026-05-15
429
408
 
@@ -436,13 +415,11 @@ See `docs/migrations/0.1.19.md`.
436
415
  - New round subprocess env vars `AGENT_RUNNER_ROUND_NUM` and
437
416
  `AGENT_RUNNER_PHASE`.
438
417
 
439
- See `docs/migrations/0.1.17.md`.
440
-
441
418
  ## [0.1.16] - 2026-05-14
442
419
 
443
420
  ### ⚠️ Breaking changes
444
421
 
445
- - **`runtime.round_timeout_per_phase` dict syntax removed**. Use `[phases.<name>] round_timeout_s = X` sub-table instead. Migration recipe in `docs/migrations/0.1.16.md`. Rationale: the dict syntax scaled poorly (N² as more per-phase fields would land); the sub-table is a one-time generalization that accommodates any per-phase field including the new `prompt.files`.
422
+ - **`runtime.round_timeout_per_phase` dict syntax removed**. Use `[phases.<name>] round_timeout_s = X` sub-table instead. Rationale: the dict syntax scaled poorly (N² as more per-phase fields would land); the sub-table is a one-time generalization that accommodates any per-phase field including the new `prompt.files`.
446
423
  - **`Config.phases` type changed** from `list[str] | None` to `PhasesConfig` dataclass with `.list: list[str] | None` and `.overrides: dict[str, PhaseOverride]`. Code reading `cfg.phases` as a list directly must update to `cfg.phases.list`. Internal callers and plugins are advised to check this access pattern.
447
424
 
448
425
  ### Added
@@ -456,7 +433,7 @@ See `docs/migrations/0.1.17.md`.
456
433
 
457
434
  ### Migration notes
458
435
 
459
- - Replace `runtime.round_timeout_per_phase = { dev = 3600, qa = 900 }` with `[phases.dev] round_timeout_s = 3600` + `[phases.qa] round_timeout_s = 900` sub-tables. See `docs/migrations/0.1.16.md` for full recipe.
436
+ - Replace `runtime.round_timeout_per_phase = { dev = 3600, qa = 900 }` with `[phases.dev] round_timeout_s = 3600` + `[phases.qa] round_timeout_s = 900` sub-tables.
460
437
  - Code reading `cfg.phases` (e.g. iterating phase names) must update to `cfg.phases.list`.
461
438
  - `prompt.file = "x.md"` continues to work unchanged; no migration required unless adopting multi-file concat.
462
439
 
@@ -0,0 +1,120 @@
1
+ # Contributing to agent-runner
2
+
3
+ Thanks for your interest in contributing!
4
+
5
+ ## Development setup
6
+
7
+ ```bash
8
+ git clone https://github.com/wan9yu/cli-agent-runner.git
9
+ cd cli-agent-runner
10
+ python3 -m venv .venv && source .venv/bin/activate
11
+ pip install -e ".[dev]"
12
+ ./build.sh check
13
+ ```
14
+
15
+ `./build.sh check` runs the full local-CI sweep: ruff (lint + format), unit
16
+ + integration tests, the literate quickstart, and the docs CI gate. It's
17
+ what GitHub Actions runs on every push and PR.
18
+
19
+ ## Workflow
20
+
21
+ 1. Open an issue first for non-trivial changes — saves wasted work on both sides.
22
+ 2. Branch off `main`. Keep PRs focused; one logical change per PR.
23
+ 3. **TDD encouraged**: write the failing test first, then the implementation.
24
+ 4. Every public API change needs a home for each new fact — see
25
+ [Where does this fact go?](#where-does-this-fact-go) below.
26
+ 5. Run `./build.sh check` locally before pushing.
27
+ 6. Conventional Commits: `feat:` / `fix:` / `docs:` / `refactor:` / `test:` /
28
+ `chore:` / `ci:` / `build:` / `perf:`. Subjects in English, imperative mood.
29
+ CI (`lint-commits` job) and `tests/invariants/test_no_ai_signatures.py`
30
+ reject auto-generated trailers and robot signatures — keep messages
31
+ human-authored.
32
+
33
+ ## Where does this fact go?
34
+
35
+ Before you write a sentence into a doc, run it through these four questions in
36
+ order. The first one that matches is the fact's home — put it there and nowhere
37
+ else. This is mechanical: a contributor (or an AI) should reach the same answer
38
+ without judgment.
39
+
40
+ 1. **Is it enumerable/mechanical?** A default, enum, flag, count, schema,
41
+ transform, or preset. → It lives in **code as data**. The doc gets a
42
+ `gen:` block that renders it (see the generated regions in `docs/*.md`,
43
+ filled by `./build.sh docs`) or it gets nothing. Never hand-copy the value
44
+ into prose.
45
+
46
+ 2. **Is it a behavioral claim?** "X happens when Y." → It lives in a **test**.
47
+ The doc may name that test — the path is data, and a named test that goes
48
+ red is a self-correcting reference. Prose that asserts behavior no test
49
+ pins is a claim waiting to rot.
50
+
51
+ 3. **Is it judgment, rationale, or narrative?** Why a design is the way it is,
52
+ a trade-off, a walkthrough. → It's **authored prose**; write it. If that
53
+ prose must name an owned fact (e.g. a config default) to make its point,
54
+ declare it inline with `<!-- authored: reason; SSOT <source> -->` so the
55
+ mention is a reviewed choice, not silent drift.
56
+
57
+ 4. **None of the above?** → **Delete it.** A fact with no home is upkeep with
58
+ no reader.
59
+
60
+ The corollary: **a fact stated twice is a bug with a delay timer.** The two
61
+ copies will diverge; the only question is when. Derive one from the other, or
62
+ delete one.
63
+
64
+ This isn't only convention. `tests/invariants/test_authored_facts_declared.py`
65
+ enforces (1) and (3) for config defaults today: a known config field named
66
+ alongside a default literal in prose fails the gate unless it carries an
67
+ `<!-- authored: reason -->` declaration. The linter's scope grows over time —
68
+ more owned facts, more of this procedure, mechanically enforced.
69
+
70
+ ## Migration docs
71
+
72
+ Migration guidance is primarily the executable `agent-runner migrate` command
73
+ (which rewrites removed/renamed config fields — its transform list is generated
74
+ into `docs/commands.md` from the registry) plus `CHANGELOG.md`. Between them
75
+ they carry a config rewrite and per-version notes; a doc that only restates the
76
+ changelog is upkeep with no reader.
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.`).
82
+
83
+ Migration guides are **not** append-only. A per-version guide is pruned once its
84
+ content becomes executable (`migrate`), generated (the transform list),
85
+ consolidated (into `0.2.md`), or purely archival — its live referrers retargeted
86
+ in the same change so no dead pointer remains. When you consolidate, correct a
87
+ carried-over step in place rather than preserving the original wording.
88
+
89
+ ## Architecture / docs
90
+
91
+ - [`docs/architecture.md`](docs/architecture.md) — 3-layer model, defenses-as-data.
92
+ - [`docs/commands.md`](docs/commands.md) — verb reference.
93
+ - [`docs/configuration.md`](docs/configuration.md) — TOML schema.
94
+
95
+ The defenses table, detector list, event kinds, config schema, and verb
96
+ table in `docs/*.md` are auto-generated by `./build.sh docs`. The CI gate
97
+ fails if those regions drift from the code's source of truth. Don't edit
98
+ them manually — edit the generator or the data source.
99
+
100
+ `.vulture-whitelist.py` is likewise generated — from every `@dataclass` field
101
+ in `agent_runner/`. If you add or rename a dataclass field, run
102
+ `./build.sh vulture-whitelist` and commit the regenerated file;
103
+ `tests/invariants/test_vulture_whitelist_generated.py` fails the gate if it
104
+ drifts.
105
+
106
+ ## Tests
107
+
108
+ - Unit + integration: `pytest -q --ignore=tests/e2e --ignore=tests/literate`
109
+ - Literate quickstart: `./build.sh literate`
110
+ - Pi e2e (opt-in): `AGENT_RUNNER_E2E_PI=1 pytest tests/e2e/` (needs a `pi`
111
+ ssh alias; not run in CI).
112
+
113
+ ## Code of conduct
114
+
115
+ Project follows the [Contributor Covenant v2.1](CODE_OF_CONDUCT.md). Be kind.
116
+
117
+ ## Reporting security issues
118
+
119
+ Please **don't** open public issues for security problems — see
120
+ [SECURITY.md](SECURITY.md).
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: cli-agent-runner
3
- Version: 0.2.8
3
+ Version: 0.2.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
@@ -128,24 +128,17 @@ agent-runner monitor # 30s poll
128
128
  agent-runner monitor --json | jq -c # pipe to downstream consumers
129
129
  ```
130
130
 
131
- Watch a remote host's event stream from your laptop one command instead of a
132
- hand-rolled `ssh … ; sleep` loop:
131
+ Watch a remote host's event stream from your laptop with a managed ssh relay
132
+ one command instead of a hand-rolled `ssh … ; sleep` loop:
133
133
 
134
134
  ```bash
135
135
  agent-runner monitor --host pi --mode events # managed ssh relay, JSONL stdout
136
136
  ```
137
137
 
138
- The relay reconnects with `--since <last ts>` so a dropped link replays its gap,
139
- gives up (exit 1) once the outage passes `remote_failure_tolerance_s`, and kills
140
- the ssh process group on exit so no orphan tree is left behind.
141
-
142
- > **Detection stays on the host.** `--host` with `--mode anomaly | narrate |
143
- > http` exits with an error: the detectors read the supervised host's logs and
144
- > auto-stop its service, which must keep working with your laptop closed. Run
145
- > the monitor there (`ssh <alias>`, then `agent-runner monitor`) and relay its
146
- > events here. See [`docs/runbook.md`](docs/runbook.md) § "Remote event relay &
147
- > SSH trust" — the SSH trust boundary applies to any agent-runner command you
148
- > drive over ssh.
138
+ Detection stays on the host: `--host` with `--mode anomaly | narrate | http`
139
+ exits with an error, since the detectors and auto-stop must keep working with
140
+ your laptop closed. Full relay + SSH-trust mechanics:
141
+ [`docs/runbook.md`](docs/runbook.md) § "Remote event relay & SSH trust".
149
142
 
150
143
  ## Documentation
151
144
 
@@ -92,24 +92,17 @@ agent-runner monitor # 30s poll
92
92
  agent-runner monitor --json | jq -c # pipe to downstream consumers
93
93
  ```
94
94
 
95
- Watch a remote host's event stream from your laptop one command instead of a
96
- hand-rolled `ssh … ; sleep` loop:
95
+ Watch a remote host's event stream from your laptop with a managed ssh relay
96
+ one command instead of a hand-rolled `ssh … ; sleep` loop:
97
97
 
98
98
  ```bash
99
99
  agent-runner monitor --host pi --mode events # managed ssh relay, JSONL stdout
100
100
  ```
101
101
 
102
- The relay reconnects with `--since <last ts>` so a dropped link replays its gap,
103
- gives up (exit 1) once the outage passes `remote_failure_tolerance_s`, and kills
104
- the ssh process group on exit so no orphan tree is left behind.
105
-
106
- > **Detection stays on the host.** `--host` with `--mode anomaly | narrate |
107
- > http` exits with an error: the detectors read the supervised host's logs and
108
- > auto-stop its service, which must keep working with your laptop closed. Run
109
- > the monitor there (`ssh <alias>`, then `agent-runner monitor`) and relay its
110
- > events here. See [`docs/runbook.md`](docs/runbook.md) § "Remote event relay &
111
- > SSH trust" — the SSH trust boundary applies to any agent-runner command you
112
- > drive over ssh.
102
+ Detection stays on the host: `--host` with `--mode anomaly | narrate | http`
103
+ exits with an error, since the detectors and auto-stop must keep working with
104
+ your laptop closed. Full relay + SSH-trust mechanics:
105
+ [`docs/runbook.md`](docs/runbook.md) § "Remote event relay & SSH trust".
113
106
 
114
107
  ## Documentation
115
108
 
@@ -156,6 +156,13 @@ def render_event_kinds_list() -> str:
156
156
  return "\n".join(f"- `{k}`" for k in sorted(KNOWN_EVENT_KINDS))
157
157
 
158
158
 
159
+ def _render_migrate_transforms() -> str:
160
+ """Bullet list of the transforms `agent-runner migrate` applies, from the registry."""
161
+ from agent_runner.migrations import MIGRATIONS
162
+
163
+ return "\n".join(f"- {m.describe}" for m in MIGRATIONS)
164
+
165
+
159
166
  def _subparser_action() -> argparse.Action:
160
167
  """The single ``_SubParsersAction`` on the top-level parser."""
161
168
  from agent_runner.cli import _build_parser
@@ -227,20 +234,50 @@ def _render_preset(name: str) -> str:
227
234
  return "```toml\n" + body.rstrip() + "\n```"
228
235
 
229
236
 
230
- RENDERERS: dict[str, Callable[[], str]] = {
231
- "defenses-table": render_defenses_table,
232
- "detector-list": render_detector_list,
233
- "event-kinds": render_event_kinds_list,
234
- "config-schema": render_config_schema_table,
235
- "verb-table": render_verb_table,
237
+ class Renderer(typing.NamedTuple):
238
+ """A gen block's renderer paired with the code SSOT it renders from.
239
+
240
+ Source lives beside the callable at the registration site — the same paired
241
+ shape as ``_SECTIONS`` — so a block can never exist without declaring its
242
+ provenance; the gap is unrepresentable, not caught at render time.
243
+ """
244
+
245
+ fn: Callable[[], str]
246
+ source: str
247
+
248
+
249
+ RENDERERS: dict[str, Renderer] = {
250
+ "defenses-table": Renderer(render_defenses_table, "agent_runner/defenses.py catalog()"),
251
+ "detector-list": Renderer(
252
+ render_detector_list,
253
+ "agent_runner/monitor.py KNOWN_ALERT_KINDS / AUTO_STOP_ALERTS",
254
+ ),
255
+ "event-kinds": Renderer(render_event_kinds_list, "agent_runner/events.py KNOWN_EVENT_KINDS"),
256
+ "config-schema": Renderer(render_config_schema_table, "agent_runner/config.py dataclasses"),
257
+ "verb-table": Renderer(render_verb_table, "agent_runner/cli argparse subparsers"),
258
+ "migrate-transforms": Renderer(
259
+ _render_migrate_transforms, "agent_runner/migrations.py MIGRATIONS"
260
+ ),
236
261
  }
237
262
  RENDERERS.update(
238
263
  {
239
- f"flags-{v}": functools.partial(_render_verb_flags, v)
264
+ f"flags-{v}": Renderer(
265
+ functools.partial(_render_verb_flags, v),
266
+ f"agent_runner/cli {v} argparse flags",
267
+ )
240
268
  for v in ("init", "monitor", "serve", "migrate")
241
269
  }
242
270
  )
243
- RENDERERS.update({f"preset-{n}": functools.partial(_render_preset, n) for n in _preset_names()})
271
+ RENDERERS.update(
272
+ {
273
+ f"preset-{n}": Renderer(
274
+ functools.partial(_render_preset, n),
275
+ f"agent_runner/presets/{n}.toml",
276
+ )
277
+ for n in _preset_names()
278
+ }
279
+ )
280
+
244
281
 
245
282
  _GEN_OPEN = re.compile(r"<!-- gen:([a-z0-9-]+) -->")
246
283
 
@@ -264,8 +301,10 @@ def render(docs_dir: Path, *, write: bool = True) -> dict[Path, str]:
264
301
  raise ValueError(
265
302
  f"{md.name}: unknown gen marker {name!r} — valid names: {sorted(RENDERERS)}"
266
303
  )
304
+ r = RENDERERS[name]
267
305
  try:
268
- text = replace_block(text, name, RENDERERS[name]())
306
+ body = f"<!-- source: {r.source} -->\n{r.fn()}"
307
+ text = replace_block(text, name, body)
269
308
  except ValueError as e:
270
309
  raise ValueError(f"{md.name}: {e}") from e
271
310
  out[md] = text
@@ -28,6 +28,7 @@ __all__ = [
28
28
  "emit_round_substrate_after",
29
29
  "emit_round_substrate_before",
30
30
  "emit_schedule_paused",
31
+ "emit_schedule_phase_skipped",
31
32
  "emit_schedule_resumed",
32
33
  "emit_stop_file_detected",
33
34
  "emit_transient_error_backoff_capped",
@@ -98,17 +99,35 @@ def emit_stop_file_detected(
98
99
 
99
100
 
100
101
  def emit_schedule_paused(
101
- log_dir: Path, *, active_window: str, resume_at: str, timezone: str
102
+ log_dir: Path, *, active_window: str, resume_at: str, timezone: str, phase: str = ""
102
103
  ) -> None:
103
- """Emit schedule_paused when the serve loop enters a configured pause window."""
104
+ """Emit schedule_paused when the serve loop enters a configured pause window.
105
+
106
+ ``phase`` is the phase the supervisor is waiting for on a phase-aware pause;
107
+ it is omitted from the payload when empty so the legacy (non-phase) pause
108
+ stays byte-identical to 0.2.7."""
104
109
  from agent_runner.events import SCHEDULE_PAUSED, emit
105
110
 
111
+ fields = {"active_window": active_window, "resume_at": resume_at, "timezone": timezone}
112
+ if phase:
113
+ fields["phase"] = phase
114
+ emit(log_dir, SCHEDULE_PAUSED, **fields)
115
+
116
+
117
+ def emit_schedule_phase_skipped(
118
+ log_dir: Path, *, round_num: int, skipped: list[str], chosen: str | None, active_window: str
119
+ ) -> None:
120
+ """Emit schedule_phase_skipped when phase_policy=skip steps over closed phases
121
+ to reach the first runnable one this round."""
122
+ from agent_runner.events import SCHEDULE_PHASE_SKIPPED, emit
123
+
106
124
  emit(
107
125
  log_dir,
108
- SCHEDULE_PAUSED,
126
+ SCHEDULE_PHASE_SKIPPED,
127
+ round_num=round_num,
128
+ skipped=skipped,
129
+ chosen=chosen,
109
130
  active_window=active_window,
110
- resume_at=resume_at,
111
- timezone=timezone,
112
131
  )
113
132
 
114
133
 
@@ -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.2.8'
22
- __version_tuple__ = version_tuple = (0, 2, 8)
21
+ __version__ = version = '0.2.9'
22
+ __version_tuple__ = version_tuple = (0, 2, 9)
23
23
 
24
24
  __commit_id__ = commit_id = None