docs(cron): document CronScheduler provider + cron.provider key

Phase 3.5. cron-internals.md gateway-integration section now describes the
pluggable trigger (resolve_cron_scheduler, built-in default, plugins/cron
discovery, the never-without-a-trigger fallback, and the trigger-vs-execution
split). cli-commands.md notes cron.provider near the hermes cron entry.
This commit is contained in:
Ben 2026-06-18 14:18:31 +10:00
parent abbd8646eb
commit bfb6e0bb33
2 changed files with 31 additions and 1 deletions

View file

@ -102,7 +102,30 @@ tick()
### Gateway Integration
In gateway mode, the scheduler runs in a dedicated background thread (`_start_cron_ticker` in `gateway/run.py`) that calls `scheduler.tick()` every 60 seconds alongside message handling.
In gateway mode, the cron **trigger** (the part that decides *when* a due job
fires — "Axis B") is selected through a pluggable `CronScheduler` provider. The
gateway calls `resolve_cron_scheduler()` (`cron/scheduler_provider.py`) and runs
the resolved provider's `start()` in a dedicated background thread, alongside a
separate gateway-housekeeping thread.
The active provider is chosen by the `cron.provider` config key:
- **empty (default)** → the built-in `InProcessCronScheduler`, which runs the
historical in-process loop calling `scheduler.tick()` every 60 seconds. This
is byte-identical to the pre-provider behavior.
- **a named provider** (e.g. `chronos`, a managed-cron provider for
scale-to-zero deployments) → discovered from `plugins/cron/<name>/` or
`$HERMES_HOME/plugins/<name>/`.
If a named provider is missing, fails to load, or reports `is_available() ==
False`, the resolver falls back to the built-in with a warning — **cron is
never left without a trigger.** The built-in provider lives in core
(`cron/scheduler_provider.py`), not in `plugins/`, so the fallback can't be
accidentally removed.
What "firing" *means* (job execution + delivery) is unchanged and shared by all
providers — it stays in `scheduler.run_job()` / `scheduler._deliver_result()`.
A provider only controls the trigger, never execution.
In CLI mode, cron jobs only fire when `hermes cron` commands are run or during active CLI sessions.

View file

@ -533,6 +533,13 @@ hermes cron <list|create|edit|pause|resume|run|remove|status|tick>
| `status` | Check whether the cron scheduler is running. |
| `tick` | Run due jobs once and exit. |
The cron **trigger** is pluggable via the `cron.provider` config key. Empty
(the default) uses the built-in in-process ticker. A named provider (e.g.
`chronos`, a managed-cron provider for scale-to-zero deployments) is discovered
from `plugins/cron/<name>/` or `$HERMES_HOME/plugins/<name>/`; an unknown or
unavailable provider falls back to the built-in, so cron is never left without
a trigger. See the [cron internals](../developer-guide/cron-internals.md#gateway-integration) doc.
## `hermes kanban`
```bash