cli-agent-runner 0.2.8__tar.gz → 0.2.10__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 (285) hide show
  1. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/.vulture-whitelist.py +20 -0
  2. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/CHANGELOG.md +37 -48
  3. cli_agent_runner-0.2.10/CONTRIBUTING.md +120 -0
  4. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/PKG-INFO +7 -14
  5. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/README.md +6 -13
  6. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/_docgen.py +48 -9
  7. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/_emit.py +31 -6
  8. cli_agent_runner-0.2.10/agent_runner/_throttle.py +220 -0
  9. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/_version.py +2 -2
  10. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/agent_runtime.py +14 -12
  11. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/api.py +16 -28
  12. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/api_types.py +2 -0
  13. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/builtin_plugins/claude_rate_limit.py +6 -4
  14. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/builtin_plugins/codewhale.py +6 -3
  15. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/builtin_plugins/gemini.py +5 -3
  16. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/builtin_plugins/kimi.py +5 -3
  17. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/builtin_plugins/pi.py +3 -2
  18. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/cli/events_cmd.py +3 -3
  19. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/cli/peek_cmd.py +2 -2
  20. cli_agent_runner-0.2.10/agent_runner/cli/serve_cmd.py +518 -0
  21. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/cli/service_cmd.py +3 -4
  22. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/cli/upgrade_cmd.py +10 -10
  23. cli_agent_runner-0.2.10/agent_runner/clock.py +79 -0
  24. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/config.py +167 -33
  25. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/events.py +6 -3
  26. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/http_progress.py +1 -0
  27. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/metrics.py +2 -2
  28. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/migrations.py +26 -0
  29. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/monitor.py +4 -3
  30. cli_agent_runner-0.2.10/agent_runner/phase_select.py +124 -0
  31. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/remote_relay.py +3 -3
  32. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/runner.py +22 -18
  33. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/schedule.py +5 -4
  34. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/startup_check.py +34 -13
  35. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/vcs_state.py +4 -3
  36. cli_agent_runner-0.2.10/docs/README.md +45 -0
  37. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/docs/architecture.md +8 -17
  38. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/docs/commands.md +23 -17
  39. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/docs/configuration.md +135 -36
  40. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/docs/long-running-agents.md +27 -84
  41. cli_agent_runner-0.2.10/docs/migrations/0.2.md +155 -0
  42. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/docs/plugins.md +69 -230
  43. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/docs/recipes/aider.md +4 -2
  44. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/docs/recipes/codewhale.md +1 -0
  45. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/docs/runbook.md +86 -8
  46. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/docs/thesis.md +1 -1
  47. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/pyproject.toml +5 -0
  48. cli_agent_runner-0.2.10/tests/_clock.py +43 -0
  49. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/integration/test_context_enricher_namespacing.py +9 -1
  50. cli_agent_runner-0.2.10/tests/invariants/_docs.py +18 -0
  51. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/invariants/test_architecture.py +5 -2
  52. cli_agent_runner-0.2.10/tests/invariants/test_authored_facts_declared.py +77 -0
  53. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/invariants/test_config_error_consistency.py +4 -3
  54. cli_agent_runner-0.2.10/tests/invariants/test_doc_test_pointers_exist.py +22 -0
  55. cli_agent_runner-0.2.10/tests/invariants/test_doc_usage_event_fields.py +32 -0
  56. cli_agent_runner-0.2.10/tests/invariants/test_gen_blocks_name_their_source.py +28 -0
  57. cli_agent_runner-0.2.10/tests/invariants/test_no_raw_time.py +136 -0
  58. cli_agent_runner-0.2.10/tests/invariants/test_phase_select_stateless.py +53 -0
  59. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_api_observation.py +1 -1
  60. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_claude_error_detector.py +6 -6
  61. cli_agent_runner-0.2.10/tests/unit/test_emit_schedule_phase_skipped.py +39 -0
  62. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_events.py +2 -4
  63. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_events_cmd_tail.py +2 -2
  64. cli_agent_runner-0.2.10/tests/unit/test_example_dirty_handler.py +46 -0
  65. cli_agent_runner-0.2.10/tests/unit/test_example_plugin.py +65 -0
  66. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_gemini_plugin.py +2 -2
  67. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_kimi_plugin.py +1 -1
  68. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_metrics.py +2 -7
  69. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_migrations.py +24 -0
  70. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_peek_schedule.py +14 -0
  71. cli_agent_runner-0.2.10/tests/unit/test_phase_agent_launch.py +110 -0
  72. cli_agent_runner-0.2.10/tests/unit/test_phase_profiles.py +120 -0
  73. cli_agent_runner-0.2.10/tests/unit/test_phase_select.py +187 -0
  74. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_pi_plugin.py +1 -1
  75. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_runner_throttle.py +115 -27
  76. cli_agent_runner-0.2.10/tests/unit/test_serve_phase_schedule.py +454 -0
  77. cli_agent_runner-0.2.8/CONTRIBUTING.md +0 -83
  78. cli_agent_runner-0.2.8/agent_runner/_throttle.py +0 -142
  79. cli_agent_runner-0.2.8/agent_runner/cli/serve_cmd.py +0 -326
  80. cli_agent_runner-0.2.8/docs/README.md +0 -40
  81. cli_agent_runner-0.2.8/docs/migrations/0.1.28.md +0 -176
  82. cli_agent_runner-0.2.8/docs/migrations/0.2.0.md +0 -165
  83. cli_agent_runner-0.2.8/docs/migrations/0.2.1.md +0 -77
  84. cli_agent_runner-0.2.8/docs/migrations/0.2.2.md +0 -242
  85. cli_agent_runner-0.2.8/docs/migrations/0.2.3.md +0 -44
  86. cli_agent_runner-0.2.8/docs/migrations/0.2.4.md +0 -66
  87. cli_agent_runner-0.2.8/docs/migrations/0.2.5.md +0 -99
  88. cli_agent_runner-0.2.8/docs/migrations/0.2.6.md +0 -127
  89. cli_agent_runner-0.2.8/docs/migrations/0.2.7.md +0 -121
  90. cli_agent_runner-0.2.8/docs/migrations/0.2.8.md +0 -79
  91. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/.codecov.yml +0 -0
  92. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  93. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  94. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  95. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  96. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/.github/workflows/ci.yml +0 -0
  97. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/.github/workflows/release.yml +0 -0
  98. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/.gitignore +0 -0
  99. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/BACKLOG.md +0 -0
  100. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/CODE_OF_CONDUCT.md +0 -0
  101. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/LICENSE +0 -0
  102. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/README.zh.md +0 -0
  103. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/SECURITY.md +0 -0
  104. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/__init__.py +0 -0
  105. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/_redact.py +0 -0
  106. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/_registry.py +0 -0
  107. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/_substrate.py +0 -0
  108. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/builtin_plugins/__init__.py +0 -0
  109. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/builtin_plugins/_constants.py +0 -0
  110. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/builtin_plugins/default_dirty_handler.py +0 -0
  111. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/cli/__init__.py +0 -0
  112. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/cli/__main__.py +0 -0
  113. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/cli/common.py +0 -0
  114. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/cli/init_cmd.py +0 -0
  115. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/cli/install_cmd.py +0 -0
  116. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/cli/migrate_cmd.py +0 -0
  117. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/cli/monitor_cmd.py +0 -0
  118. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/cli/round_cmd.py +0 -0
  119. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/context_store.py +0 -0
  120. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/defenses.py +0 -0
  121. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/hooks.py +0 -0
  122. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/lifecycle.py +0 -0
  123. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/presets/__init__.py +0 -0
  124. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/presets/aider.toml +0 -0
  125. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/presets/claude.toml +0 -0
  126. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/presets/codewhale.toml +0 -0
  127. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/presets/gemini.toml +0 -0
  128. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/presets/kimi.toml +0 -0
  129. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/presets/pi.toml +0 -0
  130. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/prompt_loader.py +0 -0
  131. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/round_log.py +0 -0
  132. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/round_view.py +0 -0
  133. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/scaffold.py +0 -0
  134. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/agent_runner/service_unit.py +0 -0
  135. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/build.sh +0 -0
  136. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/docs/events.md +0 -0
  137. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/docs/quickstart.md +0 -0
  138. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/docs/recipes/kimi.md +0 -0
  139. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/docs/recipes/pi.md +0 -0
  140. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/__init__.py +0 -0
  141. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/_test_helpers.py +0 -0
  142. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/conftest.py +0 -0
  143. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/contract/__init__.py +0 -0
  144. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/contract/test_public_api_surface.py +0 -0
  145. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/e2e/__init__.py +0 -0
  146. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/e2e/conftest.py +0 -0
  147. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/e2e/test_e2e_graceful_stop.py +0 -0
  148. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/e2e/test_e2e_install_systemd.py +0 -0
  149. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/e2e/test_e2e_monitor_remote.py +0 -0
  150. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/e2e/test_e2e_round_lifecycle.py +0 -0
  151. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/fixtures/cli-real-output/claude-2.1.143-assistant-tool-use.jsonl +0 -0
  152. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/fixtures/cli-real-output/claude-2.1.143-result-event.jsonl +0 -0
  153. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/fixtures/cli-real-output/gemini-0.42.0-result-event.jsonl +0 -0
  154. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/generate_vulture_whitelist.py +0 -0
  155. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/integration/__init__.py +0 -0
  156. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/integration/test_bounded_run.py +0 -0
  157. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/integration/test_dirty_handler_seam.py +0 -0
  158. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/integration/test_fresh_eyes_signal.py +0 -0
  159. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/integration/test_grace_kill_emission.py +0 -0
  160. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/integration/test_install_dry_run.py +0 -0
  161. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/integration/test_monitor_seeded.py +0 -0
  162. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/integration/test_plugin_detector_loaded.py +0 -0
  163. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/integration/test_plugin_owned_paths.py +0 -0
  164. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/integration/test_plugin_real_flow.py +0 -0
  165. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/integration/test_prompt_delivery_stdin.py +0 -0
  166. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/integration/test_run_one_round_with_fake_agent.py +0 -0
  167. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/integration/test_scaffold_presets.py +0 -0
  168. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/integration/test_serve_loop.py +0 -0
  169. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/integration/test_substrate_fingerprint.py +0 -0
  170. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/integration/test_transient_error_backoff.py +0 -0
  171. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/invariants/__init__.py +0 -0
  172. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/invariants/_event_scan.py +0 -0
  173. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/invariants/test_atomic_write_enforced.py +0 -0
  174. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/invariants/test_auto_stop_policy_ssot.py +0 -0
  175. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/invariants/test_catalogs.py +0 -0
  176. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/invariants/test_classification_ssot.py +0 -0
  177. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/invariants/test_config_value_set_ssot.py +0 -0
  178. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/invariants/test_doc_builtin_plugins.py +0 -0
  179. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/invariants/test_doc_claims_match_ssot.py +0 -0
  180. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/invariants/test_doc_cli_claims.py +0 -0
  181. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/invariants/test_doc_operator_surface.py +0 -0
  182. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/invariants/test_doc_transient_error_claims.py +0 -0
  183. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/invariants/test_docs_generated.py +0 -0
  184. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/invariants/test_docs_index_complete.py +0 -0
  185. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/invariants/test_entry_points_resolve.py +0 -0
  186. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/invariants/test_event_kind_registry.py +0 -0
  187. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/invariants/test_event_kinds_ssot.py +0 -0
  188. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/invariants/test_events_doc_contract.py +0 -0
  189. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/invariants/test_hook_contract_docs.py +0 -0
  190. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/invariants/test_layer_2_loop_size.py +0 -0
  191. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/invariants/test_module_boundaries.py +0 -0
  192. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/invariants/test_module_sizes.py +0 -0
  193. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/invariants/test_no_ai_signatures.py +0 -0
  194. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/invariants/test_no_pytest_skip_on_parse_fail.py +0 -0
  195. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/invariants/test_peek_schema_version.py +0 -0
  196. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/invariants/test_plugins_config_stable.py +0 -0
  197. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/invariants/test_readme_zh_is_pointer.py +0 -0
  198. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/invariants/test_repo_constants_patched_in_tests.py +0 -0
  199. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/invariants/test_round_result_stable.py +0 -0
  200. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/invariants/test_set_diff_for_auto_tool_classification.py +0 -0
  201. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/invariants/test_stash_uses_sha_not_index.py +0 -0
  202. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/invariants/test_upstream_schema_canary.py +0 -0
  203. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/invariants/test_vulture_whitelist_generated.py +0 -0
  204. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/literate/__init__.py +0 -0
  205. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/literate/parser.py +0 -0
  206. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/literate/test_parser.py +0 -0
  207. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/literate/test_quickstart.py +0 -0
  208. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/__init__.py +0 -0
  209. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_agent_runtime.py +0 -0
  210. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_agent_runtime_grace.py +0 -0
  211. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_agent_runtime_progress.py +0 -0
  212. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_agent_runtime_signal_name.py +0 -0
  213. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_api_assemble_prompt.py +0 -0
  214. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_api_events_stream.py +0 -0
  215. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_api_install.py +0 -0
  216. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_api_read_round_num.py +0 -0
  217. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_api_resolve_phase.py +0 -0
  218. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_api_service.py +0 -0
  219. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_api_types.py +0 -0
  220. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_auto_stop_gating.py +0 -0
  221. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_catalogs.py +0 -0
  222. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_cli.py +0 -0
  223. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_cli_common.py +0 -0
  224. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_cli_init_install.py +0 -0
  225. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_cli_monitor_http.py +0 -0
  226. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_cli_service_peek_monitor.py +0 -0
  227. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_cli_upgrade.py +0 -0
  228. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_codewhale_plugin.py +0 -0
  229. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_config.py +0 -0
  230. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_config_fresh_eyes.py +0 -0
  231. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_config_max_rounds.py +0 -0
  232. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_config_prompt_delivery.py +0 -0
  233. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_config_schedule.py +0 -0
  234. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_config_stop_file.py +0 -0
  235. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_config_substrate_fingerprint_paths.py +0 -0
  236. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_config_transient_error_action.py +0 -0
  237. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_context_store.py +0 -0
  238. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_default_dirty_handler.py +0 -0
  239. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_defenses.py +0 -0
  240. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_detector_protocol.py +0 -0
  241. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_dirty_handlers.py +0 -0
  242. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_docgen.py +0 -0
  243. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_emit_config_migrated.py +0 -0
  244. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_emit_schedule.py +0 -0
  245. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_events_cmd.py +0 -0
  246. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_exit_cause.py +0 -0
  247. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_fresh_eyes_trigger.py +0 -0
  248. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_hook_failure_isolation.py +0 -0
  249. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_hooks.py +0 -0
  250. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_http_progress.py +0 -0
  251. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_init_entry_points.py +0 -0
  252. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_lifecycle.py +0 -0
  253. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_migrate_cmd.py +0 -0
  254. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_monitor_assembly.py +0 -0
  255. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_monitor_detect_anomaly_repetitive.py +0 -0
  256. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_monitor_detect_rate_limit.py +0 -0
  257. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_monitor_detect_supervisor_stale.py +0 -0
  258. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_monitor_detectors.py +0 -0
  259. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_monitor_remote.py +0 -0
  260. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_monitor_schedule_pause.py +0 -0
  261. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_network_blip_signal_guard.py +0 -0
  262. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_peek_argparse.py +0 -0
  263. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_peek_select.py +0 -0
  264. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_plugin_constants.py +0 -0
  265. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_presets.py +0 -0
  266. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_prompt_loader.py +0 -0
  267. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_redact.py +0 -0
  268. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_round_log_helpers.py +0 -0
  269. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_round_view.py +0 -0
  270. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_runner.py +0 -0
  271. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_scaffold.py +0 -0
  272. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_schedule.py +0 -0
  273. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_serve_cmd_bounded.py +0 -0
  274. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_serve_config_broken.py +0 -0
  275. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_serve_crash_loop.py +0 -0
  276. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_serve_round_log.py +0 -0
  277. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_serve_schedule_gate.py +0 -0
  278. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_serve_sentinel.py +0 -0
  279. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_serve_startup_hooks.py +0 -0
  280. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_service_unit.py +0 -0
  281. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_startup_check.py +0 -0
  282. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_substrate.py +0 -0
  283. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_throttle_plugin_classification.py +0 -0
  284. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_upgrade_migrate.py +0 -0
  285. {cli_agent_runner-0.2.8 → cli_agent_runner-0.2.10}/tests/unit/test_vcs_state.py +0 -0
@@ -57,6 +57,7 @@ throttled_until_epoch
57
57
  limit_type
58
58
  agent
59
59
  since_round
60
+ phase
60
61
 
61
62
  # agent_runner.api_types.RoundResult
62
63
  round_num
@@ -106,6 +107,7 @@ reset_at_epoch
106
107
  classification
107
108
  agent
108
109
  since_round
110
+ phase
109
111
 
110
112
  # agent_runner.config.AgentConfig
111
113
  command
@@ -144,15 +146,24 @@ disk_critical_pct
144
146
  round_timeout_s
145
147
  disable_pre_round_hooks
146
148
  prompt_files
149
+ agent
150
+ schedule
147
151
 
148
152
  # agent_runner.config.PhasesConfig
149
153
  list
150
154
  overrides
155
+ phase_policy
151
156
 
152
157
  # agent_runner.config.PluginsConfig
153
158
  disable
154
159
  raw
155
160
 
161
+ # agent_runner.config.Profile
162
+ agent
163
+ runtime
164
+ schedule
165
+ prompt_files
166
+
156
167
  # agent_runner.config.PromptConfig
157
168
  file
158
169
  files
@@ -245,6 +256,15 @@ manual
245
256
  # agent_runner.monitor.LocalSource
246
257
  log_dir
247
258
 
259
+ # agent_runner.phase_select.Selection
260
+ phase
261
+ paused
262
+ resume_at
263
+ resume_phase
264
+ resume_timezone
265
+ skipped
266
+ active_window
267
+
248
268
  # agent_runner.round_log.PruneOutcome
249
269
  deleted
250
270
  deferred
@@ -5,6 +5,28 @@ 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.10] - 2026-08-29
9
+
10
+ ### Added
11
+ - Throttle-aware skip: under `[phases] phase_policy = "skip"`, a phase whose provider is currently rate-limited/erroring is stepped over in the rotation — a healthy sibling runs instead of the whole loop sleeping on the throttle. No new config; the trigger is the existing `skip` policy.
12
+ - `transient_error_detected` now carries the failing `phase`; `peek --json` `rate_limit` and the HTTP progress state surface which phase is throttled.
13
+ - `transient_error_recovered` is emitted when a skip-around throttle clears (events-derived, restart-safe, no double-emit with the back-off path).
14
+
15
+ ### Notes
16
+ - Only `skip` routes around a throttle; `wait`, `--ignore-schedule`, and non-`[phases]` configs keep the 0.2.9 global back-off. When every phase is throttled or window-closed, the loop waits until the earlier of a window opening or the throttle resetting.
17
+
18
+ See `docs/migrations/0.2.md`.
19
+
20
+ ## [0.2.9] - 2026-08-28
21
+
22
+ ### Added
23
+ - 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.
24
+ - `[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.
25
+ - `[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.
26
+ - `agent-runner migrate` reports (does not rewrite) flat per-phase runtime overrides that can move under `[phases.<name>.runtime]`.
27
+
28
+ See `docs/migrations/0.2.md`.
29
+
8
30
  ## [0.2.8] - 2026-08-25
9
31
 
10
32
  ### Added
@@ -14,7 +36,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
14
36
  ### Changed
15
37
  - Removed-field `ConfigError` messages now point to `agent-runner migrate`.
16
38
 
17
- See `docs/migrations/0.2.8.md`.
39
+ See `docs/migrations/0.2.md`.
18
40
 
19
41
  ## [0.2.7] - 2026-08-25
20
42
 
@@ -26,7 +48,7 @@ See `docs/migrations/0.2.8.md`.
26
48
  ### Fixed
27
49
  - Monitor no longer raises `supervisor_stale` during an intentional schedule pause (suppressed until `resume_at` plus one staleness window).
28
50
 
29
- See `docs/migrations/0.2.7.md`.
51
+ See `docs/migrations/0.2.md`.
30
52
 
31
53
  ## [0.2.6] - 2026-07-28
32
54
 
@@ -39,7 +61,7 @@ See `docs/migrations/0.2.7.md`.
39
61
  ### Added
40
62
  - `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
63
 
42
- See `docs/migrations/0.2.6.md`.
64
+ See `docs/migrations/0.2.md`.
43
65
 
44
66
  ## [0.2.5] - 2026-07-27
45
67
 
@@ -50,7 +72,7 @@ See `docs/migrations/0.2.6.md`.
50
72
  ### Removed
51
73
  - 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
74
 
53
- See `docs/migrations/0.2.5.md`.
75
+ See `docs/migrations/0.2.md`.
54
76
 
55
77
  ## [0.2.4] - 2026-07-27
56
78
 
@@ -67,7 +89,7 @@ See `docs/migrations/0.2.5.md`.
67
89
  - 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
90
  - 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
91
 
70
- See `docs/migrations/0.2.4.md`.
92
+ See `docs/migrations/0.2.md`.
71
93
 
72
94
  ## [0.2.3] - 2026-07-26
73
95
 
@@ -79,7 +101,7 @@ See `docs/migrations/0.2.4.md`.
79
101
  - 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
102
  - 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
103
 
82
- See `docs/migrations/0.2.3.md`.
104
+ See `docs/migrations/0.2.md`.
83
105
 
84
106
  ## [0.2.2] - 2026-07-18
85
107
 
@@ -102,7 +124,7 @@ See `docs/migrations/0.2.3.md`.
102
124
  ### Added
103
125
  - 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
126
 
105
- See `docs/migrations/0.2.2.md`.
127
+ See `docs/migrations/0.2.md`.
106
128
 
107
129
  ## [0.2.1] - 2026-07-16
108
130
 
@@ -113,7 +135,7 @@ See `docs/migrations/0.2.2.md`.
113
135
  ### Fixed
114
136
  - 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
137
 
116
- See `docs/migrations/0.2.1.md`.
138
+ See `docs/migrations/0.2.md`.
117
139
 
118
140
  ## [0.2.0] - 2026-07-02
119
141
 
@@ -121,7 +143,7 @@ See `docs/migrations/0.2.1.md`.
121
143
  - 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
144
 
123
145
  ### 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`.
146
+ - `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
147
  - `dirty_auto_committed` event (emitted when a handler auto-commits).
126
148
 
127
149
  ## [0.1.42] - 2026-06-25
@@ -150,7 +172,7 @@ See `docs/migrations/0.2.1.md`.
150
172
  ### Security
151
173
  - 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
174
  - 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`.
175
+ - Pre-0.1.40 `events-*.jsonl` may contain unredacted argv/excerpts.
154
176
 
155
177
  ### Changed
156
178
  - Docs: `configuration.md` `[monitor.host_health]` example points to the generated schema table instead of restating default values.
@@ -206,7 +228,7 @@ See `docs/migrations/0.2.1.md`.
206
228
  ## [0.1.35] - 2026-05-20
207
229
 
208
230
  ### 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.
231
+ - `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
232
 
211
233
  ## [0.1.34] - 2026-05-20
212
234
 
@@ -218,8 +240,6 @@ See `docs/migrations/0.2.1.md`.
218
240
  ### Removed
219
241
  - `peek --select events.<kind>` selector (mis-placed in state-snapshot verb). Use `events --kind <kind>` instead. 1-line `s///` migration.
220
242
 
221
- See `docs/migrations/0.1.34.md`.
222
-
223
243
  ## [0.1.33] - 2026-05-19
224
244
 
225
245
  ### Added
@@ -228,8 +248,6 @@ See `docs/migrations/0.1.34.md`.
228
248
  - `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
249
  - `docs/thesis.md` names the server-authoritative vs estimated reset principle.
230
250
 
231
- See `docs/migrations/0.1.33.md`.
232
-
233
251
  ## [0.1.32] - 2026-05-18
234
252
 
235
253
  ### Added
@@ -238,8 +256,6 @@ See `docs/migrations/0.1.33.md`.
238
256
  - `[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
257
  - New monitor detector `anomaly_repetitive_active` (notify) — alerts when `anomaly_repetitive_tool` events fire in recent rounds. Detector count 10 → 11.
240
258
 
241
- See `docs/migrations/0.1.32.md`.
242
-
243
259
  ## [0.1.31] - 2026-05-18
244
260
 
245
261
  ### Added
@@ -248,8 +264,6 @@ See `docs/migrations/0.1.32.md`.
248
264
  - `[runtime] dry_run` boolean exposed via `HookContext.dry_run` for plugin authors to skip side-effect actions when set.
249
265
  - Documentation: TOML changes require daemon restart (no hot-reload); phase rotation indexing clarification.
250
266
 
251
- See `docs/migrations/0.1.31.md`.
252
-
253
267
  ## [0.1.30] - 2026-05-18
254
268
 
255
269
  ### Fixed
@@ -262,8 +276,6 @@ See `docs/migrations/0.1.31.md`.
262
276
  - `docs/thesis.md` — project non-goals SSOT for feature-request evaluation.
263
277
  - README + runbook callouts for SSH trust boundary of `monitor --host`.
264
278
 
265
- See `docs/migrations/0.1.30.md`.
266
-
267
279
  ## [0.1.29] - 2026-05-17
268
280
 
269
281
  ### Added
@@ -278,8 +290,6 @@ See `docs/migrations/0.1.30.md`.
278
290
  - Legacy API exports: `emit_rate_limit_rejected`, `emit_rate_limit_recovered`, `emit_rate_limit_backoff_capped`.
279
291
  - Config alias `runtime.rate_limit_action` — use `runtime.transient_error_action`. Removed configs now error with migration hint.
280
292
 
281
- See `docs/migrations/0.1.29.md`.
282
-
283
293
  ## [0.1.28] - 2026-05-17
284
294
 
285
295
  ### Added
@@ -295,7 +305,7 @@ See `docs/migrations/0.1.29.md`.
295
305
  - `agent_runner.api_types.ThrottleState` dead alias (0.1.23 back-compat; deprecation window
296
306
  passed; switch to `TransientErrorState`).
297
307
 
298
- See `docs/migrations/0.1.28.md`.
308
+ See `docs/plugins.md` under `claude_error_detector` for the `agent_usage_recorded` payload schema.
299
309
 
300
310
  ## [0.1.27] - 2026-05-17
301
311
 
@@ -305,11 +315,9 @@ See `docs/migrations/0.1.28.md`.
305
315
  Affects supervisors consuming transient_error_detected.
306
316
 
307
317
  ### Added
308
- - docs/migrations/0.1.27.md: supervisor usage guide for transient_error_detected event
318
+ - Supervisor usage guide for transient_error_detected event
309
319
  (4-bucket dispatch table + back-off recipe).
310
320
 
311
- See `docs/migrations/0.1.27.md`.
312
-
313
321
  ## [0.1.26] - 2026-05-17
314
322
 
315
323
  - Fix claude `agent_usage_recorded` `model` field (was always
@@ -322,8 +330,6 @@ See `docs/migrations/0.1.27.md`.
322
330
  `gemini_error_detector` plugin can parse output. Existing scaffolds
323
331
  need manual TOML edit; round log format changes (text → JSONL).
324
332
 
325
- See `docs/migrations/0.1.26.md`.
326
-
327
333
  ## [0.1.25] - 2026-05-17
328
334
 
329
335
  - **Hotfix**: built-in `claude_error_detector` and `gemini_error_detector`
@@ -334,8 +340,6 @@ See `docs/migrations/0.1.26.md`.
334
340
  - `HookContext.agent_log_path: Path | None = None` (additive). 3rd-party
335
341
  plugin authors reading `ctx.log_dir / "round-{N}.log"` should migrate.
336
342
 
337
- See `docs/migrations/0.1.25.md`.
338
-
339
343
  ## [0.1.24] - 2026-05-17
340
344
 
341
345
  - New `agent_usage_recorded` event: per-round token + cost data, emitted
@@ -348,8 +352,6 @@ See `docs/migrations/0.1.25.md`.
348
352
  unattended operation (gemini CLI refuses headless runs in untrusted
349
353
  dirs). Existing scaffolds need manual edit.
350
354
 
351
- See `docs/migrations/0.1.24.md`.
352
-
353
355
  ## [0.1.23] - 2026-05-17
354
356
 
355
357
  - Generalized claude error handling: new `transient_error_*` event family
@@ -362,8 +364,6 @@ See `docs/migrations/0.1.24.md`.
362
364
  - Plugin `claude_rate_limit_detector` renamed to `claude_error_detector`
363
365
  (entry-point alias preserved).
364
366
 
365
- See `docs/migrations/0.1.23.md`.
366
-
367
367
  ## [0.1.22] - 2026-05-16
368
368
 
369
369
  - `[runtime] substrate_fingerprint_paths` + `round_substrate_before` /
@@ -376,8 +376,6 @@ See `docs/migrations/0.1.23.md`.
376
376
  - New `docs/long-running-agents.md`: hazards + 4 primitives + framework
377
377
  abstraction boundary.
378
378
 
379
- See `docs/migrations/0.1.22.md`.
380
-
381
379
  ## [0.1.21] - 2026-05-16
382
380
 
383
381
  - `[runtime] max_rounds = N` + `--max-rounds N` CLI flag: supervisor
@@ -388,8 +386,6 @@ See `docs/migrations/0.1.22.md`.
388
386
  `systemctl start` to resume.
389
387
  - 2 new events: `max_rounds_reached`, `stop_file_detected`.
390
388
 
391
- See `docs/migrations/0.1.21.md`.
392
-
393
389
  ## [0.1.20] - 2026-05-16
394
390
 
395
391
  - Built-in detection of claude rate-limit rejections (5h OAuth quota).
@@ -402,8 +398,6 @@ See `docs/migrations/0.1.21.md`.
402
398
  - `peek --json` schema bumped 1.8 → 1.9 (additive `rate_limit` field).
403
399
  - New monitor detector `rate_limit_active` (warning, no auto-stop).
404
400
 
405
- See `docs/migrations/0.1.20.md`.
406
-
407
401
  ## [0.1.19] - 2026-05-15
408
402
 
409
403
  - `agent-runner install` derives `ExecStart` via `shutil.which`; fixes
@@ -415,15 +409,12 @@ See `docs/migrations/0.1.20.md`.
415
409
  - New `gemini` preset: `agent-runner init --preset gemini` scaffolds
416
410
  for Gemini CLI (uses `--yolo` for unattended operation).
417
411
 
418
- See `docs/migrations/0.1.19.md`.
419
-
420
412
  ## [0.1.18] - 2026-05-15
421
413
 
422
414
  ### ⚠️ Breaking
423
415
 
424
416
  - `vcs.orphan_action` removed (deprecated in 0.1.17). TOML using the
425
417
  old key raises `ValueError` with migration hint. Use `vcs.dirty_action`.
426
- See `docs/migrations/0.1.17.md`.
427
418
 
428
419
  ## [0.1.17] - 2026-05-15
429
420
 
@@ -436,13 +427,11 @@ See `docs/migrations/0.1.19.md`.
436
427
  - New round subprocess env vars `AGENT_RUNNER_ROUND_NUM` and
437
428
  `AGENT_RUNNER_PHASE`.
438
429
 
439
- See `docs/migrations/0.1.17.md`.
440
-
441
430
  ## [0.1.16] - 2026-05-14
442
431
 
443
432
  ### ⚠️ Breaking changes
444
433
 
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`.
434
+ - **`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
435
  - **`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
436
 
448
437
  ### Added
@@ -456,7 +445,7 @@ See `docs/migrations/0.1.17.md`.
456
445
 
457
446
  ### Migration notes
458
447
 
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.
448
+ - 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
449
  - Code reading `cfg.phases` (e.g. iterating phase names) must update to `cfg.phases.list`.
461
450
  - `prompt.file = "x.md"` continues to work unchanged; no migration required unless adopting multi-file concat.
462
451
 
@@ -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.10
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