mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-25 17:18:11 +00:00
Running any state-writing `hermes cron` CLI command as root (the default for `docker exec`) rewrote jobs.json via mkstemp + atomic_replace, leaving it root:root mode 600. The gateway's ticker (uid 1000 via PUID/PGID) was then locked out of every tick with PermissionError — silently: the liveness heartbeat stayed fresh, `hermes cron status` opened with 'Gateway is running — cron jobs will fire automatically', and in the field ~14h of scheduled jobs were skipped before a human noticed the absence of messages. Fixes, per the issue's suggested items 1 and 3: 1. Ownership preservation on save (cron/jobs.py): snapshot the owner before the atomic replace; when the writer is privileged (euid 0) and the previous owner differs, chown the rewritten file back. First-time creation inherits the cron dir's owner. Unprivileged writers never call chown. POSIX-only (guarded via os.name/getattr), best-effort — a chown failure logs a warning but never breaks the save. 0600 hardening is unchanged. 2. Zombie-ticker surfacing: the ticker loop (both single-profile and multiplex paths) now persists the failure reason to a ticker_last_error marker next to the heartbeat files on every failed tick, and clears it on the next clean tick. `hermes cron status` shows the recorded reason in its 'ticks may be failing' branch, plus an actionable ownership hint when the error is a PermissionError (recommend `docker exec -u <uid>:<gid>`). Fixes #68483 |
||
|---|---|---|
| .. | ||
| __init__.py | ||
| conftest.py | ||
| test_blueprint_catalog.py | ||
| test_claim_job_for_fire.py | ||
| test_codex_execution_paths.py | ||
| test_compute_next_run_last_run_at.py | ||
| test_cron_context_from.py | ||
| test_cron_direct_api_call_62151.py | ||
| test_cron_inactivity_timeout.py | ||
| test_cron_no_agent.py | ||
| test_cron_profile_isolation.py | ||
| test_cron_prompt_injection_skill.py | ||
| test_cron_provider_pin.py | ||
| test_cron_script.py | ||
| test_cron_workdir.py | ||
| test_cronjob_schema.py | ||
| test_execution_ledger.py | ||
| test_file_permissions.py | ||
| test_jobs.py | ||
| test_jobs_changed_notify.py | ||
| test_jobs_crossprocess_lock.py | ||
| test_jobs_file_ownership.py | ||
| test_parallel_pool.py | ||
| test_reasoning_config_per_model.py | ||
| test_rewrite_skill_refs.py | ||
| test_run_one_job.py | ||
| test_scheduler.py | ||
| test_scheduler_mcp_init.py | ||
| test_scheduler_provider.py | ||
| test_scheduler_shutdown_guard.py | ||
| test_script_claim_heartbeat.py | ||
| test_sessiondb_init_hang.py | ||
| test_shutdown_interrupt.py | ||
| test_suggestions.py | ||
| test_terminal_cwd_lock.py | ||
| test_ticker_stall_60703.py | ||