From d943c034780ec384498e5cd3b6114ff3ccd4ec3e Mon Sep 17 00:00:00 2001 From: toki Date: Thu, 13 Aug 2026 21:17:30 +0900 Subject: [PATCH] =?UTF-8?q?fix(agent-ops):=20stall=20=EC=9D=B4=ED=9B=84=20?= =?UTF-8?q?=EC=83=88=20=EC=84=B8=EC=85=98=EC=9D=84=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- agent-ops/.version | 2 +- .../skills/common/orchestrate-agent-task-loop/SKILL.md | 1 + .../orchestrate-agent-task-loop/scripts/dispatch.py | 10 +++++++--- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/agent-ops/.version b/agent-ops/.version index afdf04e..56fd1c0 100644 --- a/agent-ops/.version +++ b/agent-ops/.version @@ -1 +1 @@ -1.1.199 +1.1.200 diff --git a/agent-ops/skills/common/orchestrate-agent-task-loop/SKILL.md b/agent-ops/skills/common/orchestrate-agent-task-loop/SKILL.md index ba9750a..0587305 100644 --- a/agent-ops/skills/common/orchestrate-agent-task-loop/SKILL.md +++ b/agent-ops/skills/common/orchestrate-agent-task-loop/SKILL.md @@ -113,6 +113,7 @@ Accept self-check completion only when `## Implementation Checklist` or its supp - Determine liveness from PID/start-token/process-marker evidence and actual stream or native-session progress. Heartbeat mtime is never agent progress. For Codex JSONL, an unmatched `item.started` `command_execution` is an active tool interval: suspend the model-response silence timer until its matching `item.completed`, then restore normal stall detection. - The dispatcher model-silence safety net is 70 seconds. Downstream provider runtimes should emit their bounded terminal before that deadline; do not extend the dispatcher budget per target to cover nested retries. - Treat a confirmed provider transport terminal as the end of the current dispatch. Do not resume or automatically resend the same native session; an operator may start a fresh dispatch after the provider/runtime state is corrected. +- Retry `session-stall` only with a fresh native conversation. Preserve workspace changes and logical locator evidence, but do not carry the silent conversation context into the next attempt or a restarted dispatcher. - Never start a duplicate attempt while owned live evidence remains. - Keep a 10-consecutive-failure budget per task stage. Reset only that stage's budget after success. - Preserve failed attempt logs. Delete successful attempt logs only after verified archive completion and no live evidence. diff --git a/agent-ops/skills/common/orchestrate-agent-task-loop/scripts/dispatch.py b/agent-ops/skills/common/orchestrate-agent-task-loop/scripts/dispatch.py index 6930dd3..8477be1 100644 --- a/agent-ops/skills/common/orchestrate-agent-task-loop/scripts/dispatch.py +++ b/agent-ops/skills/common/orchestrate-agent-task-loop/scripts/dispatch.py @@ -3253,7 +3253,7 @@ def native_resume_locator( if ( not isinstance(record.get("runtime"), dict) or not record["runtime"].get("native_session_monitor") - or record.get("failure_class") not in {"context-limit", "session-stall"} + or record.get("failure_class") != "context-limit" or record.get("status") != "failed" ): return None @@ -4690,7 +4690,7 @@ async def run_escalating( ], ) previous_locator = locator - native_resume_locator = locator + native_resume_locator = locator if failure == "context-limit" else None await asyncio.sleep(min(30, 2 ** min(native_recovery_retries, 5))) continue native_recovery_retries += 1 @@ -5341,7 +5341,11 @@ async def run_worker( resume_locator: Path | None = None, ) -> None: retry_context = store.task_state(task).get("retry_failover_context") - if resume_locator is None and isinstance(retry_context, dict): + if ( + resume_locator is None + and isinstance(retry_context, dict) + and retry_context.get("failure_class") not in PROVIDER_TRANSPORT_FAILURES + ): locator_value = retry_context.get("locator") if isinstance(locator_value, str) and locator_value: resume_locator = Path(locator_value)