Fixes#351
Root cause: cron jobs with a per-job model override (e.g. `gemma4:latest`,
8K context) were only discovered to be incompatible at agent runtime,
causing a hard ValueError on every tick with no automatic recovery.
Changes:
- Add `CRON_MIN_CONTEXT_TOKENS = 64_000` constant to scheduler.py
- Add `ModelContextError(ValueError)` exception class for typed identification
- Add `_check_model_context_compat()` preflight function that calls
`get_model_context_length()` and raises `ModelContextError` if the
resolved model's context is below the minimum
- Call preflight check in `run_job()` after model resolution, before
`AIAgent()` is instantiated
- In `_process_single_job()` inside `tick()`, catch `ModelContextError`
and call `pause_job()` to auto-pause the offending job — it will no
longer fire on every tick until the operator fixes the config
- Honour `model.context_length` in config.yaml as an explicit override
that bypasses the check (operator accepts responsibility)
- If context detection itself fails (network/import error), log a warning
and allow the job to proceed (fail-open) so detection gaps don't block
otherwise-working jobs
- Fix pre-existing IndentationError in `tick()` result loop (missing
`try:` block introduced in #353 parallel-execution refactor)
- Export `ModelContextError` and `CRON_MIN_CONTEXT_TOKENS` from `cron/__init__.py`
- Add 8 new tests covering all branches of `_check_model_context_compat`
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>