This commit is contained in:
David Elliott 2026-04-24 19:26:13 -05:00 committed by GitHub
commit f5be112957
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 47 additions and 1 deletions

View file

@ -122,6 +122,31 @@ _LOCK_DIR = _hermes_home / "cron"
_LOCK_FILE = _LOCK_DIR / ".tick.lock" _LOCK_FILE = _LOCK_DIR / ".tick.lock"
def _build_role_prompt_prefix(job: dict) -> str:
"""Return optional role-specific execution guidance for a cron job."""
role = str(job.get("role") or "").strip().lower()
if role == "study":
return (
"[SYSTEM: This cron job is classified as role=study. Treat it as an execution loop, not a passive summary. "
"When a run confirms a durable gap, convert that gap into explicit follow-through before you report: update the "
"owning backlog/control surface in the target repo, and if the gap is really Hermes's own capability "
"(planning, verification, delegation, evidence handling, candidate selection, or similar), also create or "
"update Hermes self-improvement work via self_improvement_pipeline or an equivalent backlog issue when those "
"tools are available. If you decide no action is warranted yet, say why in the report instead of silently "
"continuing.]"
)
if role == "self-improve":
return (
"[SYSTEM: This cron job is classified as role=self-improve. Treat stale or missing evidence as a concrete "
"follow-through item, not a passive observation. If self_improvement_pipeline or self_improvement_evidence_gate "
"shows journal_entries stale or missing, either refresh the owning journal/control surface with a legitimate "
"new entry when this run produced a real durable outcome, or leave the reliability floor degraded and report "
"the exact external blocker. Do not claim the issue is fixed without advancing the journal source itself, and "
"do not mask true stale evidence.]"
)
return ""
def _resolve_origin(job: dict) -> Optional[dict]: def _resolve_origin(job: dict) -> Optional[dict]:
"""Extract origin info from a job, preserving any extra routing metadata.""" """Extract origin info from a job, preserving any extra routing metadata."""
origin = job.get("origin") origin = job.get("origin")
@ -684,7 +709,8 @@ def _build_job_prompt(job: dict, prerun_script: Optional[tuple] = None) -> str:
"Never combine [SILENT] with content — either report your " "Never combine [SILENT] with content — either report your "
"findings normally, or say [SILENT] and nothing more.]\n\n" "findings normally, or say [SILENT] and nothing more.]\n\n"
) )
prompt = cron_hint + prompt role_prefix = _build_role_prompt_prefix(job)
prompt = cron_hint + (role_prefix + "\n\n" if role_prefix else "") + prompt
if skills is None: if skills is None:
legacy = job.get("skill") legacy = job.get("skill")
skills = [legacy] if legacy else [] skills = [legacy] if legacy else []

View file

@ -1269,6 +1269,26 @@ class TestBuildJobPromptSilentHint:
prompt_pos = result.index("My custom prompt") prompt_pos = result.index("My custom prompt")
assert system_pos < prompt_pos assert system_pos < prompt_pos
def test_study_role_injects_execution_guidance(self):
job = {"prompt": "Study Chapter 7", "role": "study"}
result = _build_job_prompt(job)
assert "classified as role=study" in result
assert "execution loop, not a passive summary" in result
assert "self_improvement_pipeline" in result
def test_self_improve_role_injects_journal_followthrough_guidance(self):
job = {"prompt": "Run the loop", "role": "self-improve"}
result = _build_job_prompt(job)
assert "classified as role=self-improve" in result
assert "journal_entries stale or missing" in result
assert "do not mask true stale evidence" in result
def test_non_study_role_does_not_inject_role_guidance(self):
job = {"prompt": "Send report", "role": "report"}
result = _build_job_prompt(job)
assert "classified as role=study" not in result
assert "classified as role=self-improve" not in result
class TestParseWakeGate: class TestParseWakeGate:
"""Unit tests for _parse_wake_gate — pure function, no side effects.""" """Unit tests for _parse_wake_gate — pure function, no side effects."""