Match segment window by its own action phase

For segmented beats, the repair stage now searches for the source action
window using the segment's own description first; the full beat context is
used only as a fallback or when it scores noticeably higher. The trailer-
offset shift is applied only when the beat context is actually chosen.

Also harden vision-call retries to catch read-side network errors
(TimeoutError, socket.timeout, ConnectionError, OSError) and wrap the
filter/repair loop so a transient vision failure preserves the previously
cached match instead of dropping it.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Melbar
2026-05-03 06:22:12 +02:00
parent 2cc05e4737
commit 7b4a98d760
4 changed files with 183 additions and 5 deletions
+14
View File
@@ -13,6 +13,7 @@ import base64
import json
import logging
import re
import socket
import time
import urllib.error
import urllib.request
@@ -193,6 +194,19 @@ def _call_vision_model(label: str, image_urls: list[str], cfg: AppConfig) -> str
len(delays_s),
)
time.sleep(delay_s)
except (TimeoutError, socket.timeout, ConnectionError, OSError) as exc:
if attempt >= len(delays_s):
raise RuntimeError(f"Vision request failed for {url}: {exc}") from exc
delay_s = delays_s[attempt]
logger.warning(
"Vision request network error for %s (%s); waiting %.0fs before retry %d/%d.",
label,
exc,
delay_s,
attempt + 1,
len(delays_s),
)
time.sleep(delay_s)
raise RuntimeError(f"Vision request failed unexpectedly for {url}")