fix(compression): surface an unpublished stall-fallback fence at WARNING

Review follow-up for #95433. When the host's fence factory is absent or
raises, the retry runs on a private CompressionCommitFence() that
hard-interrupt admission never reads — /stop would serialize against the
aborted attempt's fence instead of the retry's commit boundary. Promote
the factory-failure swallow from debug to warning and warn when the retry
has no published fence, so the control-plane degradation is visible rather
than silent.

Also documents the pin's coverage (single _generate_summary call; the
lean-mode chunk digests are a separate unpinned call path).
This commit is contained in:
Shaun Eccles
2026-08-27 07:59:27 +10:00
committed by kshitij
parent 2c6938dc3a
commit 6151e59d65
2 changed files with 19 additions and 2 deletions
+10
View File
@@ -72,6 +72,16 @@ def _safe_int(value: Any) -> int | None:
# with it. Context is copied per worker (``propagate_context_to_thread``), so
# the pin reaches the retry's whole synchronous call chain and cannot leak
# into the stalled attempt or any unrelated auxiliary call.
#
# Coverage is the single ``_generate_summary`` LLM call only. That is one call
# per compression run (its only non-recursive call site is the compress path;
# the two recursive calls are the deliberate main-model retry that must NOT
# re-issue the pin). Lean ``tail_mode`` additionally runs
# ``_build_chunk_digests``, which issues its own ``call_llm`` calls directly
# and never consults the pin — during a stall-fallback retry those digests
# still target the stalled primary and degrade to per-segment placeholders.
# Deliberate: the digest path is a best-effort augmentation, not the summary,
# and pinning it would require weakening the single-use contract below.
_SUMMARY_ROUTE_PIN: contextvars.ContextVar[Optional[Dict[str, Any]]] = (
contextvars.ContextVar("hermes_summary_route_pin", default=None)
)
+9 -2
View File
@@ -953,11 +953,18 @@ def _retry_compression_on_fallback_chain(
try:
retry_fence = new_fence()
except Exception:
logger.debug(
"compression stall-fallback fence factory failed",
logger.warning(
"compression stall-fallback fence factory failed; the retry "
"will run on an unpublished fence (a /stop mid-retry cannot "
"serialize against its commit boundary)",
exc_info=True,
)
if not isinstance(retry_fence, CompressionCommitFence):
logger.warning(
"compression stall-fallback retry running on an unpublished fence; "
"hard-interrupt admission will read the aborted attempt's fence "
"rather than the retry's commit boundary",
)
retry_fence = CompressionCommitFence()
idle = float(route.get("timeout") or idle_timeout_seconds)
ceiling = max(float(total_ceiling_seconds), idle)