mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-22 16:25:58 +00:00
fix(cron): patched compatibility constants take precedence over a repointed env
Review follow-up: tests that monkeypatch CRON_DIR/JOBS_FILE/OUTPUT_DIR (the documented process-wide compatibility surface) were bypassed by the lazy env fallback — 3 file-permission tests, the cross-process lock test, and the heartbeat roundtrip regressed. _current_cron_store() now snapshots the constants at import and honors any deliberate re-point of them ahead of the env resolution, so the precedence is: use_cron_store() override > patched constants > fresh HERMES_HOME > import defaults. Adds a test pinning constants-beat-env; the late-env sentinel behavior is unchanged. tests/cron: failure set byte-identical to unpatched main on this box (the 5 regressions gone); 138 pass in the touched files.
This commit is contained in:
parent
5c121f157f
commit
65d6bd2b9f
2 changed files with 38 additions and 11 deletions
36
cron/jobs.py
36
cron/jobs.py
|
|
@ -115,26 +115,40 @@ _cron_store_override: ContextVar[Optional[_CronStorePaths]] = ContextVar(
|
|||
)
|
||||
|
||||
|
||||
# Import-time snapshot of the compatibility constants, so deliberate
|
||||
# re-pointing of the module surface (monkeypatched CRON_DIR/JOBS_FILE/
|
||||
# OUTPUT_DIR — the documented escape hatch existing tests/embedders use)
|
||||
# is distinguishable from the constants merely being stale.
|
||||
_IMPORT_STORE = _CronStorePaths(CRON_DIR, JOBS_FILE, OUTPUT_DIR)
|
||||
|
||||
|
||||
def _current_cron_store() -> _CronStorePaths:
|
||||
"""Return paths pinned to this execution context's profile.
|
||||
|
||||
With no use_cron_store() override active, the active profile home is
|
||||
resolved FRESH via get_hermes_home() (context-local override, then the
|
||||
HERMES_HOME env var) instead of trusting the import-time capture. A test
|
||||
or embedder that re-points HERMES_HOME after this module was imported
|
||||
therefore reads/writes ITS OWN store — not whatever jobs.json the import
|
||||
happened to freeze (the filed incident: fixtures that patched the env too
|
||||
late silently rewrote the user's real jobs file). The module-level
|
||||
constants keep their import-time values as the documented compatibility
|
||||
surface, and the common path (home unchanged since import) still returns
|
||||
them unchanged.
|
||||
Precedence, most explicit first:
|
||||
|
||||
1. an active use_cron_store() override (ContextVar);
|
||||
2. deliberately re-pointed module constants — if CRON_DIR/JOBS_FILE/
|
||||
OUTPUT_DIR no longer match their import-time values, someone chose
|
||||
the documented process-wide compatibility surface; honor it;
|
||||
3. the ACTIVE profile home, resolved fresh via get_hermes_home()
|
||||
(context-local override, then the HERMES_HOME env var) — so a test
|
||||
or embedder that re-points HERMES_HOME after this module was
|
||||
imported reads/writes ITS OWN store, not whatever jobs.json the
|
||||
import happened to freeze (the filed incident: fixtures that patched
|
||||
the env too late silently rewrote the user's real jobs file);
|
||||
4. the import-time constants (home unchanged since import — the common
|
||||
path, returned unchanged).
|
||||
"""
|
||||
override = _cron_store_override.get()
|
||||
if override is not None:
|
||||
return override
|
||||
live_constants = _CronStorePaths(CRON_DIR, JOBS_FILE, OUTPUT_DIR)
|
||||
if live_constants != _IMPORT_STORE:
|
||||
return live_constants
|
||||
home = get_hermes_home().resolve()
|
||||
if home == HERMES_DIR:
|
||||
return _CronStorePaths(CRON_DIR, JOBS_FILE, OUTPUT_DIR)
|
||||
return live_constants
|
||||
cron_dir = home / "cron"
|
||||
return _CronStorePaths(cron_dir, cron_dir / "jobs.json", cron_dir / "output")
|
||||
|
||||
|
|
|
|||
|
|
@ -1978,3 +1978,16 @@ class TestLateEnvRepointScopesStore:
|
|||
with jobs.use_cron_store(tmp_path / "override-home"):
|
||||
store = jobs._current_cron_store()
|
||||
assert store.jobs_file == (tmp_path / "override-home").resolve() / "cron" / "jobs.json"
|
||||
|
||||
def test_patched_compatibility_constants_beat_env(self, tmp_path, monkeypatch):
|
||||
"""Deliberately re-pointed module constants are the documented
|
||||
process-wide escape hatch — they win over a repointed HERMES_HOME."""
|
||||
import cron.jobs as jobs
|
||||
|
||||
patched_dir = tmp_path / "patched-cron"
|
||||
monkeypatch.setattr(jobs, "CRON_DIR", patched_dir)
|
||||
monkeypatch.setattr(jobs, "JOBS_FILE", patched_dir / "jobs.json")
|
||||
monkeypatch.setattr(jobs, "OUTPUT_DIR", patched_dir / "output")
|
||||
monkeypatch.setenv("HERMES_HOME", str(tmp_path / "env-home"))
|
||||
store = jobs._current_cron_store()
|
||||
assert store.jobs_file == patched_dir / "jobs.json"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue