fix(vision-manager): LOW watermark must not idle-stop a running vision (#9)
Some checks failed
deploy / test-backend (push) Failing after 22m32s
deploy / test-frontend (push) Successful in 11m37s
deploy / build-and-push (push) Has been skipped
deploy / deploy (push) Has been skipped

This commit was merged in pull request #9.
This commit is contained in:
2026-06-16 16:57:49 +00:00
parent d85fba7056
commit 32fcebd47a

View File

@@ -200,19 +200,27 @@ while true; do
analysis_off=0 analysis_off=0
fi fi
# Memory-yield gates (before the backlog logic). The active stop handles a # Memory-yield: two SEPARATE levers, never conflated.
# running vision the idle path can't; the inhibit forces pending=0 so the # - active stop (HIGH watermark): mem_check_and_stop SIGTERMs a RUNNING
# existing idle-debounce path keeps it down (same shape as the crawl mutex). # vision when the host is critically short — the ONLY thing that stops a
# vision that is actively working.
# - start block (LOW watermark / cooldown): holds off STARTING a stopped
# vision when memory is already tight, via the mem_block_start flag.
# It must NOT zero `pending`: doing so made the idle-debounce path read
# "no work" and idle-stop a vision mid-analysis once the box floated past
# LOW (idle stack + LLM ≈ 80% here). LOW is a START gate, not a stop
# threshold.
mem_check_and_stop mem_check_and_stop
running="$(vision_running)" # refresh: the active stop may have just flipped it running="$(vision_running)" # refresh: the active stop may have just flipped it
mem_block_start=0
if [ "$(mem_yield_active)" = "1" ]; then if [ "$(mem_yield_active)" = "1" ]; then
mem_block_start=1
if [ "$mem_inhibited" != "1" ]; then if [ "$mem_inhibited" != "1" ]; then
log "memory-yield: inhibiting vision start (used >= ${MEM_LOW_WATERMARK_PCT}% or cooldown active)" log "memory-yield: blocking vision START (used >= ${MEM_LOW_WATERMARK_PCT}% or cooldown); a running vision keeps working until the ${MEM_HIGH_WATERMARK_PCT}% active stop"
mem_inhibited=1 mem_inhibited=1
fi fi
pending=0
elif [ "$mem_inhibited" = "1" ]; then elif [ "$mem_inhibited" = "1" ]; then
log "memory-yield: pressure cleared — start inhibit lifted" log "memory-yield: pressure cleared — start block lifted"
mem_inhibited=0 mem_inhibited=0
fi fi
@@ -225,7 +233,12 @@ while true; do
if [ "$pending" -gt 0 ]; then if [ "$pending" -gt 0 ]; then
idle_for=0 idle_for=0
if [ "$running" != "true" ]; then if [ "$running" != "true" ]; then
if [ "$RESPECT_CRAWL_MUTEX" != "0" ] && [ "$(crawl_running)" != "0" ]; then if [ "$mem_block_start" = "1" ]; then
# Memory pressure / cooldown — hold off STARTING (flip already logged).
# A RUNNING vision never reaches here; idle_for stayed 0 above because
# pending>0, so a working vision is never idle-stopped under pressure.
:
elif [ "$RESPECT_CRAWL_MUTEX" != "0" ] && [ "$(crawl_running)" != "0" ]; then
# Log once per deferral episode, not every poll, so a long crawl # Log once per deferral episode, not every poll, so a long crawl
# doesn't flood the log. # doesn't flood the log.
if [ "$crawl_deferred" != "1" ]; then if [ "$crawl_deferred" != "1" ]; then