Conversation
The fix targets a genuinely harmful misattribution: an in-process child's small iteration cap (
— reviewer-a · automated agent review (Hermes week-review) |
965ab84 to
b256342
Compare
|
Reworded the four comments flagged in review: they now state the rule itself (budget-exhaustion recording is dispatcher-owned only) instead of 'LOCAL PATCH 14' provenance numbering, so the diff reads as applying to this repo state. Tests unchanged semantically, 10/10 still green. |
b256342 to
3a2cbe8
Compare
|
Rebased onto current |
…inst the parent task HERMES_KANBAN_TASK stays set in os.environ for in-process children (delegate_task subagents, background-review forks, cron jobs fired via the cronjob tool) running inside a dispatcher worker. Those children carry their own — much smaller — iteration budgets, so a child running out of iterations was recording a terminal timed_out failure against the worker's task, advancing the dispatcher's consecutive-failure circuit breaker and archiving live work that was still running fine at the parent level. Gate the budget-exhaustion recording on the dispatcher-ownership predicate (is_dispatcher_owned_worker_context) plus the review fork's persistence-isolation marker (_persist_disabled): only the dispatcher-owned worker agent records. Rebased onto the Sep 2026 decomposition: the two former call sites are now one in finalize_turn.
3a2cbe8 to
d935450
Compare
Summary
HERMES_KANBAN_TASKstays set inos.environfor in-process children running inside a dispatcher worker:delegate_tasksubagents, background-review forks, and cron agents fired via thecronjobtool. Those children carry their own much smaller iteration budgets (review-fork cap 16,delegation.max_iterations50), so when a child exhausted ITS budget,_record_kanban_budget_exhaustedrecorded a terminaltimed_outfailure against the WORKER's task — advancing the dispatcher'sconsecutive_failurescircuit breaker and archiving live parent work that was still running fine.Observed in production: a verifier task archived after a
(16/16)exhaustion event (the background-review fork's cap, not the task's 250) and a coder task archived after(50/50)(the delegation cap, not 300). Both parent tasks were healthy; only the child had run out of budget.Fix
Gate both
_record_kanban_budget_exhaustedcall sites inagent/turn_finalizer.pyon a new_should_record_budget_exhaustion(agent)helper:is_dispatcher_owned_worker_context()— the documented single predicate forHERMES_KANBAN_*identity gates (machinery from fix(cron): don't let a cron job inherit a kanban worker's dispatcher identity #79657). False for delegated children and non-dispatcher-owned cron execution.not getattr(agent, "_persist_disabled", False)— the background-review fork's persistence-isolation marker (same idiom as the micro-compact guard in this file).Zero behavior change for genuine dispatcher-owned workers: a real worker exhausting its real budget still records
timed_outexactly as before (verified live: ContextVar token reset restores parent ownership after child scopes exit).Relationship to other PRs
turn_finalizer.py).non_dispatcher_owned_contextmachinery — extends the same identity discipline to the budget-exhaustion recording path.Test plan
test_budget_exhaustion_recorded_only_for_dispatcher_owned_worker— 5-case matrix: dispatcher-owned fires; delegated child skips; review fork skips; non-dispatcher-owned cron skips; guard truth table_persist_disabledleg, or fully reverting the guard each makes the test fail — both legs independently coveredtest_turn_finalizer_iteration_limit_exit.pypass unchanged (10/10 file total)tests/agent/suite: failure set byte-identical before/after (zero collateral)