cli-agent-runner 0.1.0__tar.gz → 0.1.6__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 (139) hide show
  1. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/.github/ISSUE_TEMPLATE/config.yml +1 -1
  2. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/.github/workflows/release.yml +37 -0
  3. cli_agent_runner-0.1.6/CHANGELOG.md +235 -0
  4. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/CONTRIBUTING.md +2 -2
  5. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/PKG-INFO +25 -22
  6. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/README.md +19 -16
  7. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/README.zh.md +16 -12
  8. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/SECURITY.md +1 -1
  9. cli_agent_runner-0.1.6/agent_runner/__init__.py +54 -0
  10. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/agent_runner/_docgen.py +2 -0
  11. cli_agent_runner-0.1.6/agent_runner/_registry.py +23 -0
  12. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/agent_runner/_version.py +2 -2
  13. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/agent_runner/api.py +12 -4
  14. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/agent_runner/api_types.py +53 -4
  15. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/agent_runner/cli/common.py +19 -1
  16. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/agent_runner/cli/install_cmd.py +1 -1
  17. cli_agent_runner-0.1.6/agent_runner/config.py +144 -0
  18. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/agent_runner/defenses.py +2 -2
  19. cli_agent_runner-0.1.6/agent_runner/detector_helpers.py +115 -0
  20. cli_agent_runner-0.1.6/agent_runner/events.py +130 -0
  21. cli_agent_runner-0.1.6/agent_runner/hooks.py +143 -0
  22. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/agent_runner/monitor.py +107 -39
  23. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/agent_runner/prompt_loader.py +3 -2
  24. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/agent_runner/runner.py +98 -18
  25. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/agent_runner/scaffold.py +3 -5
  26. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/agent_runner/startup_check.py +4 -1
  27. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/docs/architecture.md +18 -23
  28. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/docs/commands.md +1 -1
  29. cli_agent_runner-0.1.6/docs/configuration.md +103 -0
  30. cli_agent_runner-0.1.6/docs/plugins.md +311 -0
  31. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/docs/quickstart.md +29 -6
  32. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/pyproject.toml +5 -5
  33. cli_agent_runner-0.1.6/tests/integration/test_context_enricher_namespacing.py +57 -0
  34. cli_agent_runner-0.1.6/tests/integration/test_plugin_detector_loaded.py +105 -0
  35. cli_agent_runner-0.1.0/tests/invariants/test_phase2_architecture.py → cli_agent_runner-0.1.6/tests/invariants/test_architecture.py +2 -19
  36. cli_agent_runner-0.1.6/tests/invariants/test_event_kind_registry.py +74 -0
  37. cli_agent_runner-0.1.0/tests/invariants/test_phase2_module_sizes.py → cli_agent_runner-0.1.6/tests/invariants/test_module_sizes.py +7 -10
  38. cli_agent_runner-0.1.6/tests/invariants/test_peek_schema_version.py +78 -0
  39. cli_agent_runner-0.1.6/tests/invariants/test_round_result_stable.py +75 -0
  40. cli_agent_runner-0.1.6/tests/unit/test_auto_stop_gating.py +91 -0
  41. cli_agent_runner-0.1.6/tests/unit/test_config.py +331 -0
  42. cli_agent_runner-0.1.6/tests/unit/test_detector_helpers.py +141 -0
  43. cli_agent_runner-0.1.6/tests/unit/test_detector_protocol.py +69 -0
  44. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/unit/test_docgen.py +1 -1
  45. cli_agent_runner-0.1.6/tests/unit/test_events.py +150 -0
  46. cli_agent_runner-0.1.6/tests/unit/test_hook_failure_isolation.py +77 -0
  47. cli_agent_runner-0.1.6/tests/unit/test_hooks.py +139 -0
  48. cli_agent_runner-0.1.6/tests/unit/test_init_entry_points.py +107 -0
  49. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/unit/test_monitor_detectors.py +55 -0
  50. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/unit/test_prompt_loader.py +66 -0
  51. cli_agent_runner-0.1.0/CHANGELOG.md +0 -43
  52. cli_agent_runner-0.1.0/agent_runner/__init__.py +0 -3
  53. cli_agent_runner-0.1.0/agent_runner/config.py +0 -92
  54. cli_agent_runner-0.1.0/agent_runner/critic.py +0 -33
  55. cli_agent_runner-0.1.0/agent_runner/events.py +0 -53
  56. cli_agent_runner-0.1.0/docs/configuration.md +0 -78
  57. cli_agent_runner-0.1.0/tests/invariants/test_event_kind_registry.py +0 -39
  58. cli_agent_runner-0.1.0/tests/unit/test_config.py +0 -115
  59. cli_agent_runner-0.1.0/tests/unit/test_critic.py +0 -27
  60. cli_agent_runner-0.1.0/tests/unit/test_events.py +0 -79
  61. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/.codecov.yml +0 -0
  62. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  63. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  64. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  65. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/.github/workflows/ci.yml +0 -0
  66. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/.gitignore +0 -0
  67. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/.vulture-whitelist.py +0 -0
  68. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/CODE_OF_CONDUCT.md +0 -0
  69. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/LICENSE +0 -0
  70. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/agent_runner/agent_runtime.py +0 -0
  71. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/agent_runner/cli/__init__.py +0 -0
  72. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/agent_runner/cli/__main__.py +0 -0
  73. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/agent_runner/cli/init_cmd.py +0 -0
  74. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/agent_runner/cli/monitor_cmd.py +0 -0
  75. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/agent_runner/cli/peek_cmd.py +0 -0
  76. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/agent_runner/cli/round_cmd.py +0 -0
  77. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/agent_runner/cli/serve_cmd.py +0 -0
  78. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/agent_runner/cli/service_cmd.py +0 -0
  79. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/agent_runner/context_store.py +0 -0
  80. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/agent_runner/lifecycle.py +0 -0
  81. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/agent_runner/metrics.py +0 -0
  82. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/agent_runner/round_view.py +0 -0
  83. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/agent_runner/service_unit.py +0 -0
  84. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/agent_runner/vcs_state.py +0 -0
  85. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/build.sh +0 -0
  86. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/deploy/example-agent-runner.toml +0 -0
  87. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/deploy/launchd.plist.tmpl +0 -0
  88. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/deploy/run-loop.sh +0 -0
  89. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/deploy/systemd.service.tmpl +0 -0
  90. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/docs/README.md +0 -0
  91. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/docs/runbook.md +0 -0
  92. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/__init__.py +0 -0
  93. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/conftest.py +0 -0
  94. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/e2e/__init__.py +0 -0
  95. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/e2e/conftest.py +0 -0
  96. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/e2e/test_e2e_graceful_stop.py +0 -0
  97. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/e2e/test_e2e_install_systemd.py +0 -0
  98. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/e2e/test_e2e_monitor_remote.py +0 -0
  99. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/e2e/test_e2e_round_lifecycle.py +0 -0
  100. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/integration/__init__.py +0 -0
  101. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/integration/test_install_dry_run.py +0 -0
  102. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/integration/test_monitor_seeded.py +0 -0
  103. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/integration/test_run_loop_backoff.py +0 -0
  104. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/integration/test_run_one_round_with_fake_agent.py +0 -0
  105. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/integration/test_serve_loop.py +0 -0
  106. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/invariants/__init__.py +0 -0
  107. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/invariants/test_atomic_write_enforced.py +0 -0
  108. /cli_agent_runner-0.1.0/tests/invariants/test_phase2_catalogs.py → /cli_agent_runner-0.1.6/tests/invariants/test_catalogs.py +0 -0
  109. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/invariants/test_docs_generated.py +0 -0
  110. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/invariants/test_module_boundaries.py +0 -0
  111. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/invariants/test_no_pytest_skip_on_parse_fail.py +0 -0
  112. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/invariants/test_repo_constants_patched_in_tests.py +0 -0
  113. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/invariants/test_stash_uses_sha_not_index.py +0 -0
  114. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/literate/__init__.py +0 -0
  115. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/literate/parser.py +0 -0
  116. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/literate/test_parser.py +0 -0
  117. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/literate/test_quickstart.py +0 -0
  118. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/unit/__init__.py +0 -0
  119. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/unit/test_agent_runtime.py +0 -0
  120. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/unit/test_api_observation.py +0 -0
  121. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/unit/test_api_service.py +0 -0
  122. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/unit/test_api_types.py +0 -0
  123. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/unit/test_cli.py +0 -0
  124. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/unit/test_cli_common.py +0 -0
  125. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/unit/test_cli_init_install.py +0 -0
  126. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/unit/test_cli_service_peek_monitor.py +0 -0
  127. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/unit/test_context_store.py +0 -0
  128. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/unit/test_defenses.py +0 -0
  129. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/unit/test_lifecycle.py +0 -0
  130. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/unit/test_metrics.py +0 -0
  131. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/unit/test_monitor_assembly.py +0 -0
  132. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/unit/test_monitor_remote.py +0 -0
  133. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/unit/test_peek_argparse.py +0 -0
  134. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/unit/test_round_view.py +0 -0
  135. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/unit/test_runner.py +0 -0
  136. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/unit/test_scaffold.py +0 -0
  137. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/unit/test_service_unit.py +0 -0
  138. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/unit/test_startup_check.py +0 -0
  139. {cli_agent_runner-0.1.0 → cli_agent_runner-0.1.6}/tests/unit/test_vcs_state.py +0 -0
@@ -1,5 +1,5 @@
1
1
  blank_issues_enabled: false
2
2
  contact_links:
3
3
  - name: Question or usage help
4
- url: https://github.com/wan9yu/agent-runner/discussions
4
+ url: https://github.com/wan9yu/cli-agent-runner/discussions
5
5
  about: For usage questions, please open a discussion.
@@ -56,3 +56,40 @@ jobs:
56
56
  - uses: pypa/gh-action-pypi-publish@release/v1
57
57
  with:
58
58
  attestations: true
59
+
60
+ github-release:
61
+ needs: publish-pypi
62
+ runs-on: ubuntu-latest
63
+ timeout-minutes: 5
64
+ permissions:
65
+ contents: write
66
+ steps:
67
+ - uses: actions/checkout@v4
68
+ - uses: actions/download-artifact@v4
69
+ with:
70
+ name: dist
71
+ path: dist/
72
+ - name: extract CHANGELOG section for this tag
73
+ run: |
74
+ VERSION="${GITHUB_REF#refs/tags/v}"
75
+ awk -v ver="$VERSION" '
76
+ /^## \[/ {
77
+ if (found) exit
78
+ if ($0 ~ "\\[" ver "\\]") { found = 1; next }
79
+ }
80
+ found { print }
81
+ ' CHANGELOG.md > release-notes.md
82
+ if [ ! -s release-notes.md ]; then
83
+ echo "No CHANGELOG section for v$VERSION — using auto-generated notes." > release-notes.md
84
+ fi
85
+ echo "--- release-notes.md preview ---"
86
+ cat release-notes.md
87
+ - name: create GitHub Release
88
+ env:
89
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
90
+ run: |
91
+ VERSION="${GITHUB_REF#refs/tags/v}"
92
+ gh release create "v$VERSION" \
93
+ --title "v$VERSION" \
94
+ --notes-file release-notes.md \
95
+ dist/*
@@ -0,0 +1,235 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.1.6] - 2026-05-12
11
+
12
+ Zero-feature maintenance release — internal cleanup pass after the 0.1.x plugin
13
+ extension surface completed in 0.1.5. No runtime behavior change for users
14
+ without plugins; plugin authors written against 0.1.5 keep working unchanged.
15
+
16
+ ### Changed
17
+ - Public `Alert.severity` / `Alert.auto_action` and `Detector.severity` /
18
+ `Detector.auto_action` are now typed with `Severity = Literal["info", "warning",
19
+ "critical"]` and `AutoAction = Literal["none", "stop_service"]` aliases
20
+ exported from `agent_runner.api_types`. Plain-string values continue to work
21
+ - `__version__` is read from the hatch-vcs generated `_version.py` instead of a
22
+ hardcoded constant; released packages report the actual release version
23
+ - Internal duplication reduced: shared `agent_runner._registry.ensure_unique`
24
+ for hooks + detectors registries; `cli/common.emit()` plugin-namespace imports
25
+ hoisted to module top; `events.parse_iso_ms` centralizes the ISO-8601 trailing-`Z`
26
+ parsing workaround; `MonitorConfig.auto_stop_on` default now references the
27
+ `_DEFAULT_AUTO_STOP_ON` constant
28
+ - `monitor.dual_source_silence` is now TOCTOU-safe (uses `try/except
29
+ FileNotFoundError` instead of `exists()` + `stat()`)
30
+ - `api._poll_once` short-circuits when no plugin detectors are registered,
31
+ skipping `assemble_project_state` (saves a file read per local poll and an
32
+ SSH round-trip per remote poll)
33
+ - `agent_runner/__init__.py` plugin loaders share a single
34
+ `_load_plugins_from_group` helper
35
+ - `monitor._alert` no longer asserts builtin detector names against
36
+ `KNOWN_ALERT_KINDS` (assertion was redundant and would crash under
37
+ `python -O`); test + docgen layers continue to validate the builtin name set
38
+
39
+ ### Removed
40
+ - `agent_runner.critic` — empty Protocol stub for an unimplemented Critic
41
+ concept that was retired during the framework-first redesign
42
+ - `[llm]` commented block from the scaffold TOML template and its corresponding
43
+ section in `docs/configuration.md` — unused placeholder
44
+ - Legacy phase nomenclature from source docstrings, error messages, and CLI
45
+ help text; `tests/invariants/test_phase2_*.py` files renamed to drop the
46
+ `phase2_` prefix
47
+
48
+ ### Backward compatibility
49
+ - Existing `agent-runner.toml` files continue to load (the removed `[llm]`
50
+ block was never parsed by the supervisor)
51
+ - Plugin code written for 0.1.5 continues to work — Protocol contracts and
52
+ `peek --json` schema 1.3 unchanged
53
+
54
+ ## [0.1.5] - 2026-05-12
55
+
56
+ ### Added
57
+ - `agent_runner.api_types.Detector` — public Protocol for plugin detectors
58
+ (attributes `name`, `severity`, `auto_action`; method `detect(state) -> Alert | None`).
59
+ `@runtime_checkable` — plugin classes structurally satisfying the shape are accepted
60
+ - `agent_runner.monitor.register_detector(detector)` and `plugin_detectors()` — public
61
+ registration API + sorted list of currently-registered detector names
62
+ - `agent_runner.monitor.run_plugin_detectors(state)` — invokes each registered plugin
63
+ detector with the assembled `ProjectState`; per-detector exceptions surface as
64
+ `UserWarning` (round continues)
65
+ - `agent_runner` package now also discovers and loads entry_points in group
66
+ `agent_runner.detectors` at first import; failures degrade to `UserWarning`
67
+ - `agent_runner.detector_helpers` module — three production-tested helpers for
68
+ plugin detector authors:
69
+ - `cumulative_window_check(events, *, kind, window_s, min_count)` —
70
+ sliding-window event counter; robust against wall-clock skew at boundaries
71
+ - `dual_source_silence(scheduler_log, round_log, threshold_s)` — both-source
72
+ silence check; avoids false positives during long rounds when only the
73
+ scheduler log is stale
74
+ - `phase_filter(state, *, exclude_phases)` — skip detection during phases
75
+ that intentionally produce no commits (e.g., retrospective rounds)
76
+ - `MonitorConfig.auto_stop_on: list[str]` — explicit allow-list of detector
77
+ names whose `stop_service` action is honored. Defaults to
78
+ `["oauth_fail", "disk_critical"]` (builtin pair); operators must add plugin
79
+ detector names to opt them into auto-stop
80
+ - `monitor.on_alert` gains `allowed_stop_names: list[str] | None` keyword
81
+ argument; backward-compatible default falls back to the legacy builtin pair
82
+ - `peek --json` schema bumped to `"1.3"`; new `plugins.detectors: list[str]`
83
+ surfaces what's registered
84
+ - `docs/plugins.md` gains a Detector Protocol chapter + DetectorHelpers
85
+ chapter with worked examples for each helper
86
+
87
+ ### Changed
88
+ - `agent_runner.api._poll_once` now concatenates builtin detector alerts
89
+ with plugin detector alerts (`run_plugin_detectors(state)`) before returning
90
+ - `agent_runner.api.monitor_loop` threads `cfg.monitor.auto_stop_on` into
91
+ `monitor.on_alert` for strict gating
92
+ - `tests/invariants/test_peek_schema_version.py` tightened to require
93
+ `schema_version >= "1.3"` and the `plugins.detectors` list shape
94
+
95
+ ### Backward compatibility
96
+ - Zero plugins installed → monitor behavior identical to 0.1.4
97
+ - Existing 9 builtin detectors keep their current signatures unchanged
98
+ - Existing `agent-runner.toml` files load without modification; default
99
+ `auto_stop_on` matches the previously-implicit behavior
100
+ - `on_alert(...)` callers without the new kwarg continue to work via the
101
+ default `["oauth_fail", "disk_critical"]` allow-list
102
+
103
+ ## [0.1.4] - 2026-05-12
104
+
105
+ ### Added
106
+ - `agent_runner.hooks` module — three Protocol-typed plugin extension points:
107
+ `PreRoundHook` (runs after lock acquire, before context write),
108
+ `ContextEnricher` (returns a per-plugin slice stitched into `round-context.json`
109
+ under `base_context[enricher.name]`), and `PostRoundHook` (runs after agent exit,
110
+ before `round_end` event)
111
+ - `agent_runner.hooks.HookContext` — narrow runtime context passed to all hooks
112
+ (`work_dir`, `log_dir`, `project`, `round_num`, `phase`, `agent_name`); does NOT
113
+ expose the full `Config` so internal refactors remain safe
114
+ - `agent_runner.hooks.register_pre_round_hook` / `register_context_enricher` /
115
+ `register_post_round_hook` — public registration API; rejects duplicate `name`
116
+ - `agent_runner.hooks.plugin_context_enrichers()` — sorted list of registered
117
+ enricher names, surfaced via `peek --json`
118
+ - `agent_runner.api_types.RoundResult` — promoted from `runner.py`; superset of
119
+ the prior internal fields plus `phase`, `started_at`, `ended_at`, `log_path` for
120
+ stable `PostRoundHook` consumption
121
+ - `agent_runner` package now also discovers and loads three new entry_points groups
122
+ at first import: `agent_runner.pre_round_hooks`, `agent_runner.context_enrichers`,
123
+ `agent_runner.post_round_hooks`; plugin failures degrade to a `UserWarning`
124
+ - Built-in event kind `hook_failed` — emitted by the runner whenever a plugin hook
125
+ raises; payload includes `{hook_name, hook_kind, error_type, error_message, traceback}`
126
+ with traceback truncated to 2KB (head 1KB + tail 1KB joined by `[truncated]`)
127
+ - `peek --json` schema bumped to `"1.2"`; new `plugins.context_enrichers: list[str]`
128
+ - `docs/plugins.md` — new chapter with end-to-end ContextEnricher example
129
+ - New invariant `tests/invariants/test_round_result_stable.py` guards `RoundResult`
130
+ field set + types across future minors
131
+
132
+ ### Changed
133
+ - `agent_runner.runner.run_one_round` integrates hooks at three checkpoints; each
134
+ call is wrapped in `try/except` and surfaces failures via `hook_failed`
135
+ - `tests/invariants/test_peek_schema_version.py` tightened to require
136
+ `schema_version >= "1.2"` and the `plugins.context_enrichers` list shape
137
+
138
+ ### Backward compatibility
139
+ - Zero plugins installed → runner behavior identical to 0.1.3
140
+ - `RoundResult` field set is a superset; every prior field is preserved
141
+ - Existing 0.1.x user `agent-runner.toml` files load without modification
142
+
143
+ ## [0.1.3] - 2026-05-12
144
+
145
+ ### Added
146
+ - `agent_runner.events.register_event_kind(name, *, source)` — public API for plugins to register custom event kinds
147
+ - `agent_runner.events.plugin_event_kinds()` — sorted list of currently-registered plugin event kind names
148
+ - `agent_runner` package now discovers and loads entry_points in group `agent_runner.event_kinds` at first import; plugin failures degrade to a `UserWarning` instead of crashing the supervisor
149
+ - `peek --json` schema bumped to `"1.1"`; new top-level `plugins.event_kinds: list[str]` surfaces what's registered
150
+ - `docs/plugins.md` — plugin authoring stub covering the entry_points convention and the event-kind example
151
+
152
+ ### Changed
153
+ - `agent_runner.events.KNOWN_EVENT_KINDS` is now a read-only union view (built-in + plugin) instead of a `frozenset`; `in` and iteration semantics preserved
154
+ - `tests/invariants/test_event_kind_registry.py` rewritten to validate the built-in/plugin split and the registration conflict rules
155
+ - `tests/invariants/test_peek_schema_version.py` tightened to require `schema_version >= "1.1"` and the `plugins.event_kinds` list shape
156
+
157
+ ### Backward compatibility
158
+ - Every existing `from agent_runner.events import KNOWN_EVENT_KINDS` import continues to work
159
+ - Every existing `events.emit(...)` callsite continues to work with the same kind strings
160
+ - Existing 0.1.x user `agent-runner.toml` files load without modification
161
+
162
+ ## [0.1.2] - 2026-05-12
163
+
164
+ ### Added
165
+ - `cfg.agent.name` — optional provider identifier; defaults to `None` (consumers may fall back to `command[0]`)
166
+ - `cfg.prompt.context_injection_mode` — `prepend` (default) / `file` / `none`; controls how round-context reaches the agent
167
+ - `cfg.monitor.auth_fail_patterns` and `cfg.monitor.auth_fail_hint` — generalize the OAuth-fail detector for any provider
168
+ - `cfg.plugins` — placeholder for 0.1.3+ plugin enable/disable; parsed-but-unused in 0.1.2
169
+ - `peek --json` now emits top-level `schema_version: "1.0"` and `plugins: {}` namespace
170
+
171
+ ### Changed
172
+ - `startup_check` prompt-smoke error text reframed away from provider-specific wording
173
+ - `scaffold.py` generated TOML annotates `[agent]` block as the reference; encourages swapping for other CLIs
174
+ - Public docs (architecture, quickstart, configuration) reframed: the reference agent is one of many supported CLIs
175
+ - `monitor.detect_oauth_fail` now reads patterns + hint from `cfg.monitor` (SSOT migrated from a hardcoded module constant to `MonitorConfig`)
176
+
177
+ ### Backward compatibility
178
+ - All defaults preserve the existing prepend-mode behavior
179
+ - Existing `agent-runner.toml` files continue to load without modification
180
+ - Existing tests pass without modification
181
+
182
+ ## [0.1.1] — 2026-05-12
183
+
184
+ Post-release polish: PyPI install path is documented as the primary entry,
185
+ the repository was renamed for naming parity with the distribution, and the
186
+ release workflow now auto-creates GitHub Releases.
187
+
188
+ ### Changed
189
+ - README + README.zh now show `pip install cli-agent-runner` as the primary
190
+ install path; the previous `git clone` flow moved to the Development section.
191
+ - Repository renamed from `wan9yu/agent-runner` to `wan9yu/cli-agent-runner`
192
+ for parity with the PyPI distribution name. All in-tree URL references
193
+ updated; GitHub redirects keep old links working.
194
+
195
+ ### Build & CI
196
+ - Release workflow now creates a GitHub Release after PyPI publish, attaches
197
+ the sdist + wheel as release artifacts, and pulls release notes from the
198
+ matching CHANGELOG section.
199
+
200
+ ## [0.1.0] — 2026-05-12
201
+
202
+ Initial public release on PyPI as `cli-agent-runner`.
203
+
204
+ ### Added
205
+ - Three-layer model: Round / Loop / Witness.
206
+ - 13 CLI verbs: `init`, `install`, `uninstall`, `start`, `stop`, `kill`,
207
+ `cancel`, `restart`, `status`, `round`, `serve`, `peek`, `watch`, `monitor`.
208
+ - 11 named defenses (round timeout, process group isolation, orphan stash
209
+ with SHA lock, set-diff classification, smoke check, flock concurrency,
210
+ atomic state writes, event kind registry, and others).
211
+ - 9 monitor detectors (`timeout_rate`, `hung`, `orphan_chain`,
212
+ `disk_warning`, `disk_critical`, `mem_pressure`, `smoke_fail_rate`,
213
+ `oauth_fail`, `network_fail`); `oauth_fail` and `disk_critical` auto-stop
214
+ the service.
215
+ - Local-only and remote (via ssh) monitor modes.
216
+ - Auto-generated docs (`./build.sh docs`) for defenses table, detectors,
217
+ events, config schema, CLI verbs.
218
+ - Literate quickstart: `docs/quickstart.md` is executed as a pytest test.
219
+ - Python public API (`from agent_runner import api`) mirroring CLI verbs.
220
+ - Phase 3 reservation: `[llm]` config section + `agent_runner.critic`
221
+ Protocol stubs (no implementation).
222
+
223
+ ### Documentation
224
+ - English README + full Chinese `README.zh.md`.
225
+ - 5 user-facing docs: quickstart, commands, configuration, runbook, architecture.
226
+
227
+ ### Build & CI
228
+ - GitHub Actions matrix: Python 3.11/3.12/3.13 × ubuntu / macos.
229
+ - Codecov-uploaded coverage from one canonical matrix cell.
230
+ - Tag-triggered release publishing to PyPI via Trusted Publishing OIDC,
231
+ gated by a manual approval on the `pypi` GitHub environment.
232
+
233
+ [Unreleased]: https://github.com/wan9yu/cli-agent-runner/compare/v0.1.1...HEAD
234
+ [0.1.1]: https://github.com/wan9yu/cli-agent-runner/releases/tag/v0.1.1
235
+ [0.1.0]: https://github.com/wan9yu/cli-agent-runner/releases/tag/v0.1.0
@@ -5,8 +5,8 @@ Thanks for your interest in contributing!
5
5
  ## Development setup
6
6
 
7
7
  ```bash
8
- git clone https://github.com/wan9yu/agent-runner.git
9
- cd agent-runner
8
+ git clone https://github.com/wan9yu/cli-agent-runner.git
9
+ cd cli-agent-runner
10
10
  python3 -m venv .venv && source .venv/bin/activate
11
11
  pip install -e ".[dev]"
12
12
  ./build.sh check
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cli-agent-runner
3
- Version: 0.1.0
3
+ Version: 0.1.6
4
4
  Summary: Restart-on-exit supervisor for autonomous CLI agents
5
- Project-URL: Homepage, https://github.com/wan9yu/agent-runner
6
- Project-URL: Documentation, https://github.com/wan9yu/agent-runner#readme
7
- Project-URL: Repository, https://github.com/wan9yu/agent-runner
8
- Project-URL: Issues, https://github.com/wan9yu/agent-runner/issues
9
- Project-URL: Changelog, https://github.com/wan9yu/agent-runner/blob/main/CHANGELOG.md
5
+ Project-URL: Homepage, https://github.com/wan9yu/cli-agent-runner
6
+ Project-URL: Documentation, https://github.com/wan9yu/cli-agent-runner#readme
7
+ Project-URL: Repository, https://github.com/wan9yu/cli-agent-runner
8
+ Project-URL: Issues, https://github.com/wan9yu/cli-agent-runner/issues
9
+ Project-URL: Changelog, https://github.com/wan9yu/cli-agent-runner/blob/main/CHANGELOG.md
10
10
  Author-email: wangyu <wangyu@go2imagination.com>
11
11
  License-Expression: Apache-2.0
12
12
  License-File: LICENSE
@@ -37,7 +37,7 @@ Description-Content-Type: text/markdown
37
37
 
38
38
  > **[中文](README.zh.md)** · English
39
39
 
40
- [![CI](https://github.com/wan9yu/agent-runner/actions/workflows/ci.yml/badge.svg)](https://github.com/wan9yu/agent-runner/actions/workflows/ci.yml) [![PyPI](https://img.shields.io/pypi/v/cli-agent-runner.svg)](https://pypi.org/project/cli-agent-runner/) [![Python](https://img.shields.io/pypi/pyversions/cli-agent-runner.svg)](https://pypi.org/project/cli-agent-runner/) [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![codecov](https://codecov.io/gh/wan9yu/agent-runner/branch/main/graph/badge.svg)](https://codecov.io/gh/wan9yu/agent-runner) [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
40
+ [![CI](https://github.com/wan9yu/cli-agent-runner/actions/workflows/ci.yml/badge.svg)](https://github.com/wan9yu/cli-agent-runner/actions/workflows/ci.yml) [![PyPI](https://img.shields.io/pypi/v/cli-agent-runner.svg)](https://pypi.org/project/cli-agent-runner/) [![Downloads](https://img.shields.io/pypi/dm/cli-agent-runner.svg)](https://pypi.org/project/cli-agent-runner/) [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![codecov](https://codecov.io/gh/wan9yu/cli-agent-runner/branch/main/graph/badge.svg)](https://codecov.io/gh/wan9yu/cli-agent-runner)
41
41
 
42
42
  # agent-runner
43
43
 
@@ -56,15 +56,19 @@ OAuth burn loops, full disks, runaway memory.
56
56
  └──────────────────────────────────────────┘
57
57
  ```
58
58
 
59
- ## Quick start
59
+ ## Install
60
60
 
61
61
  ```bash
62
- git clone https://github.com/wan9yu/agent-runner.git
63
- cd agent-runner
64
- python3 -m venv .venv && source .venv/bin/activate
65
- pip install -e ".[dev]"
62
+ pip install cli-agent-runner
63
+ ```
64
+
65
+ The installed CLI command is `agent-runner` (the PyPI distribution name is
66
+ prefixed for namespace disambiguation; the import name and command are not).
67
+
68
+ ## Quick start
66
69
 
67
- # In your project directory:
70
+ ```bash
71
+ cd your-project
68
72
  agent-runner init # scaffold agent-runner.toml + prompts/main.md
69
73
  $EDITOR agent-runner.toml # point agent.command at your CLI
70
74
  agent-runner install --monitor # systemd user units for serve + monitor
@@ -126,18 +130,17 @@ agent-runner monitor --json | jq -c # pipe to downstream consumers
126
130
  - [`docs/runbook.md`](docs/runbook.md) — operator troubleshooting (OAuth, disk, orphan)
127
131
  - [`docs/architecture.md`](docs/architecture.md) — 3-layer model, defenses-as-data
128
132
 
129
- ## Status
130
-
131
- Phase 2 (operator surface) shipped. Phase 3 (LLM-augmented Critic) reserved —
132
- `[llm]` config block and `agent_runner.critic` Protocol stubs are in place,
133
- implementation TBD.
134
-
135
133
  ## Development
136
134
 
137
135
  ```bash
138
- pytest -q --ignore=tests/e2e # 207 unit + integration tests
139
- AGENT_RUNNER_E2E_PI=1 pytest tests/e2e/ # opt-in pi e2e (needs ssh alias `pi`)
140
- ruff check . && ruff format --check .
136
+ git clone https://github.com/wan9yu/cli-agent-runner.git
137
+ cd cli-agent-runner
138
+ python3 -m venv .venv && source .venv/bin/activate
139
+ pip install -e ".[dev]"
140
+
141
+ ./build.sh check # full local-CI sweep
142
+ ./build.sh test # unit + integration only
143
+ AGENT_RUNNER_E2E_PI=1 ./build.sh e2e # opt-in pi e2e (needs ssh alias `pi`)
141
144
  ```
142
145
 
143
146
  Some `docs/*.md` blocks are generated from code — `./build.sh docs` rewrites
@@ -1,6 +1,6 @@
1
1
  > **[中文](README.zh.md)** · English
2
2
 
3
- [![CI](https://github.com/wan9yu/agent-runner/actions/workflows/ci.yml/badge.svg)](https://github.com/wan9yu/agent-runner/actions/workflows/ci.yml) [![PyPI](https://img.shields.io/pypi/v/cli-agent-runner.svg)](https://pypi.org/project/cli-agent-runner/) [![Python](https://img.shields.io/pypi/pyversions/cli-agent-runner.svg)](https://pypi.org/project/cli-agent-runner/) [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![codecov](https://codecov.io/gh/wan9yu/agent-runner/branch/main/graph/badge.svg)](https://codecov.io/gh/wan9yu/agent-runner) [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
3
+ [![CI](https://github.com/wan9yu/cli-agent-runner/actions/workflows/ci.yml/badge.svg)](https://github.com/wan9yu/cli-agent-runner/actions/workflows/ci.yml) [![PyPI](https://img.shields.io/pypi/v/cli-agent-runner.svg)](https://pypi.org/project/cli-agent-runner/) [![Downloads](https://img.shields.io/pypi/dm/cli-agent-runner.svg)](https://pypi.org/project/cli-agent-runner/) [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![codecov](https://codecov.io/gh/wan9yu/cli-agent-runner/branch/main/graph/badge.svg)](https://codecov.io/gh/wan9yu/cli-agent-runner)
4
4
 
5
5
  # agent-runner
6
6
 
@@ -19,15 +19,19 @@ OAuth burn loops, full disks, runaway memory.
19
19
  └──────────────────────────────────────────┘
20
20
  ```
21
21
 
22
- ## Quick start
22
+ ## Install
23
23
 
24
24
  ```bash
25
- git clone https://github.com/wan9yu/agent-runner.git
26
- cd agent-runner
27
- python3 -m venv .venv && source .venv/bin/activate
28
- pip install -e ".[dev]"
25
+ pip install cli-agent-runner
26
+ ```
27
+
28
+ The installed CLI command is `agent-runner` (the PyPI distribution name is
29
+ prefixed for namespace disambiguation; the import name and command are not).
30
+
31
+ ## Quick start
29
32
 
30
- # In your project directory:
33
+ ```bash
34
+ cd your-project
31
35
  agent-runner init # scaffold agent-runner.toml + prompts/main.md
32
36
  $EDITOR agent-runner.toml # point agent.command at your CLI
33
37
  agent-runner install --monitor # systemd user units for serve + monitor
@@ -89,18 +93,17 @@ agent-runner monitor --json | jq -c # pipe to downstream consumers
89
93
  - [`docs/runbook.md`](docs/runbook.md) — operator troubleshooting (OAuth, disk, orphan)
90
94
  - [`docs/architecture.md`](docs/architecture.md) — 3-layer model, defenses-as-data
91
95
 
92
- ## Status
93
-
94
- Phase 2 (operator surface) shipped. Phase 3 (LLM-augmented Critic) reserved —
95
- `[llm]` config block and `agent_runner.critic` Protocol stubs are in place,
96
- implementation TBD.
97
-
98
96
  ## Development
99
97
 
100
98
  ```bash
101
- pytest -q --ignore=tests/e2e # 207 unit + integration tests
102
- AGENT_RUNNER_E2E_PI=1 pytest tests/e2e/ # opt-in pi e2e (needs ssh alias `pi`)
103
- ruff check . && ruff format --check .
99
+ git clone https://github.com/wan9yu/cli-agent-runner.git
100
+ cd cli-agent-runner
101
+ python3 -m venv .venv && source .venv/bin/activate
102
+ pip install -e ".[dev]"
103
+
104
+ ./build.sh check # full local-CI sweep
105
+ ./build.sh test # unit + integration only
106
+ AGENT_RUNNER_E2E_PI=1 ./build.sh e2e # opt-in pi e2e (needs ssh alias `pi`)
104
107
  ```
105
108
 
106
109
  Some `docs/*.md` blocks are generated from code — `./build.sh docs` rewrites
@@ -1,6 +1,6 @@
1
1
  > 中文 · **[English](README.md)**
2
2
 
3
- [![CI](https://github.com/wan9yu/agent-runner/actions/workflows/ci.yml/badge.svg)](https://github.com/wan9yu/agent-runner/actions/workflows/ci.yml) [![PyPI](https://img.shields.io/pypi/v/cli-agent-runner.svg)](https://pypi.org/project/cli-agent-runner/) [![Python](https://img.shields.io/pypi/pyversions/cli-agent-runner.svg)](https://pypi.org/project/cli-agent-runner/) [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![codecov](https://codecov.io/gh/wan9yu/agent-runner/branch/main/graph/badge.svg)](https://codecov.io/gh/wan9yu/agent-runner) [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
3
+ [![CI](https://github.com/wan9yu/cli-agent-runner/actions/workflows/ci.yml/badge.svg)](https://github.com/wan9yu/cli-agent-runner/actions/workflows/ci.yml) [![PyPI](https://img.shields.io/pypi/v/cli-agent-runner.svg)](https://pypi.org/project/cli-agent-runner/) [![Downloads](https://img.shields.io/pypi/dm/cli-agent-runner.svg)](https://pypi.org/project/cli-agent-runner/) [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![codecov](https://codecov.io/gh/wan9yu/cli-agent-runner/branch/main/graph/badge.svg)](https://codecov.io/gh/wan9yu/cli-agent-runner)
4
4
 
5
5
  # agent-runner
6
6
 
@@ -34,15 +34,19 @@ supervisor 重启 —— 这是核心模式。中间穿插 11 条防御,避开
34
34
  - `serve` 包住 round 形成长服务
35
35
  - `monitor` 可以从本机也可以远程通过 ssh 观测一台 pi 上的 supervisor
36
36
 
37
- ## 上手
37
+ ## 安装
38
38
 
39
39
  ```bash
40
- git clone https://github.com/wan9yu/agent-runner.git
41
- cd agent-runner
42
- python3 -m venv .venv && source .venv/bin/activate
43
- pip install -e ".[dev]"
40
+ pip install cli-agent-runner
41
+ ```
42
+
43
+ CLI 命令仍是 `agent-runner`(PyPI 包名加 `cli-` 前缀只是为了规避命名冲突,
44
+ 导入名 `agent_runner` 和命令名都不变)。
45
+
46
+ ## 上手
44
47
 
45
- # 在你的项目目录里:
48
+ ```bash
49
+ cd your-project
46
50
  agent-runner init # 生成 agent-runner.toml + prompts/main.md
47
51
  $EDITOR agent-runner.toml # 把 agent.command 指向你的 CLI
48
52
  agent-runner install --monitor # 装 systemd user unit(serve + monitor)
@@ -134,6 +138,11 @@ agent-runner monitor --json | jq -c # 输出 JSON 给下游 consumer
134
138
  ## 开发
135
139
 
136
140
  ```bash
141
+ git clone https://github.com/wan9yu/cli-agent-runner.git
142
+ cd cli-agent-runner
143
+ python3 -m venv .venv && source .venv/bin/activate
144
+ pip install -e ".[dev]"
145
+
137
146
  ./build.sh check # lint + 单元 + 集成 + literate + docs 一致性,本地 CI 全套
138
147
  ./build.sh test # 仅 230+ 单元 + 集成测试
139
148
  ./build.sh literate # 仅跑 quickstart.md 的可执行块
@@ -142,11 +151,6 @@ agent-runner monitor --json | jq -c # 输出 JSON 给下游 consumer
142
151
 
143
152
  只支持 POSIX(Linux / macOS)。Python 3.11+。x86_64 与 aarch64 都跑过。
144
153
 
145
- ## 项目状态
146
-
147
- Phase 2(运维界面)已发。Phase 3(LLM Critic)留了接口:`[llm]` 配置段 +
148
- `agent_runner.critic` Protocol stubs,实现待定。
149
-
150
154
  ## License
151
155
 
152
156
  [Apache License 2.0](LICENSE).
@@ -7,7 +7,7 @@ The latest tagged release. We do not back-port security fixes to older versions.
7
7
  ## Reporting a vulnerability
8
8
 
9
9
  Please report security issues privately via GitHub Security Advisories:
10
- <https://github.com/wan9yu/agent-runner/security/advisories/new>
10
+ <https://github.com/wan9yu/cli-agent-runner/security/advisories/new>
11
11
 
12
12
  If GitHub Security Advisories is not workable for you, email
13
13
  `wangyu@go2imagination.com` with the subject line `agent-runner security`.
@@ -0,0 +1,54 @@
1
+ """Agent Runner — restart-on-exit supervisor for autonomous CLI agents."""
2
+
3
+ from __future__ import annotations
4
+
5
+ try:
6
+ from agent_runner._version import __version__
7
+ except ImportError: # editable install before hatch-vcs has generated _version.py
8
+ __version__ = "0.0.0+unknown"
9
+
10
+ _HOOK_GROUPS = (
11
+ "agent_runner.pre_round_hooks",
12
+ "agent_runner.context_enrichers",
13
+ "agent_runner.post_round_hooks",
14
+ )
15
+
16
+
17
+ def _load_plugins_from_group(group: str) -> None:
18
+ """Discover and load entry_points in ``group``, isolating per-plugin failures.
19
+
20
+ Called at package import. A broken plugin must not crash the supervisor;
21
+ each failure surfaces as a ``UserWarning``.
22
+ """
23
+ import warnings
24
+ from importlib.metadata import entry_points
25
+
26
+ for ep in entry_points(group=group):
27
+ try:
28
+ ep.load()
29
+ except Exception as e:
30
+ warnings.warn(
31
+ f"failed to load {group} plugin {ep.name!r}: {e}",
32
+ stacklevel=3,
33
+ )
34
+
35
+
36
+ def _load_event_kind_plugins() -> None:
37
+ """Load plugins that register custom event kinds via ``events.register_event_kind``."""
38
+ _load_plugins_from_group("agent_runner.event_kinds")
39
+
40
+
41
+ def _load_hook_plugins() -> None:
42
+ """Load plugins that register pre_round / context_enricher / post_round hooks."""
43
+ for group in _HOOK_GROUPS:
44
+ _load_plugins_from_group(group)
45
+
46
+
47
+ def _load_detector_plugins() -> None:
48
+ """Load plugins that register custom monitor detectors via ``monitor.register_detector``."""
49
+ _load_plugins_from_group("agent_runner.detectors")
50
+
51
+
52
+ _load_event_kind_plugins()
53
+ _load_hook_plugins()
54
+ _load_detector_plugins()
@@ -16,6 +16,7 @@ from pathlib import Path
16
16
  from agent_runner.config import (
17
17
  AgentConfig,
18
18
  Config,
19
+ MonitorConfig,
19
20
  PromptConfig,
20
21
  RuntimeConfig,
21
22
  VcsConfig,
@@ -29,6 +30,7 @@ _SECTIONS = [
29
30
  ("runtime", RuntimeConfig),
30
31
  ("prompt", PromptConfig),
31
32
  ("vcs", VcsConfig),
33
+ ("monitor", MonitorConfig),
32
34
  ]
33
35
 
34
36
 
@@ -0,0 +1,23 @@
1
+ """Shared registry helpers for plugin-extension surfaces.
2
+
3
+ The `name`-keyed unique-registration check is identical across hooks
4
+ (:mod:`agent_runner.hooks`) and detectors (:mod:`agent_runner.monitor`).
5
+ This module is its single source of truth.
6
+
7
+ Event-kind registration in :mod:`agent_runner.events` has DIFFERENT
8
+ semantics (idempotent for same-source re-registration, conflict on
9
+ different-source) and stays in that module.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+
15
+ def ensure_unique(name: str, existing: list, kind: str) -> None:
16
+ """Raise ValueError if any item in ``existing`` already has ``.name == name``.
17
+
18
+ ``kind`` is a short label embedded in the error message (e.g. ``"detector"``,
19
+ ``"context_enricher"``).
20
+ """
21
+ for item in existing:
22
+ if getattr(item, "name", None) == name:
23
+ raise ValueError(f"{kind} {name!r} already registered; refusing to add a second")
@@ -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.1.0'
22
- __version_tuple__ = version_tuple = (0, 1, 0)
21
+ __version__ = version = '0.1.6'
22
+ __version_tuple__ = version_tuple = (0, 1, 6)
23
23
 
24
24
  __commit_id__ = commit_id = None