diff --git a/skills/continuous-learning-v2/agents/start-observer.sh b/skills/continuous-learning-v2/agents/start-observer.sh index c3ada314..096a5d7b 100755 --- a/skills/continuous-learning-v2/agents/start-observer.sh +++ b/skills/continuous-learning-v2/agents/start-observer.sh @@ -215,8 +215,12 @@ case "$ACTION" in CLV2_OBSERVER_PROMPT_PATTERN="$CLV2_OBSERVER_PROMPT_PATTERN" \ "$OBSERVER_LOOP_SCRIPT" >> "$LOG_FILE" 2>&1 & - # Wait for PID file - sleep 2 + # Wait for PID file (poll up to 10s, exits early when it appears). + # Trade-off vs the old `sleep 2`: healthy startups return in iteration 1 + # (no fixed latency), but a loop that crashes before writing the PID file + # is now detected in ~10s instead of ~2s. The longer ceiling is needed to + # tolerate slow filesystems where 2s under-waited and false-negatived. + for _i in $(seq 1 50); do [ -f "$PID_FILE" ] && break; sleep 0.2; done # Check for confirmation-seeking output in the observer log if tail -n +"$((start_line + 1))" "$LOG_FILE" 2>/dev/null | grep -E -i -q "$CLV2_OBSERVER_PROMPT_PATTERN"; then diff --git a/tests/hooks/hooks.test.js b/tests/hooks/hooks.test.js index f02bf4d1..8ccde106 100644 --- a/tests/hooks/hooks.test.js +++ b/tests/hooks/hooks.test.js @@ -3066,6 +3066,19 @@ async function runTests() { passed++; else failed++; + if ( + test('start-observer waits for PID file via poll instead of fixed sleep (#2295)', () => { + const startObserverSource = fs.readFileSync(path.join(__dirname, '..', '..', 'skills', 'continuous-learning-v2', 'agents', 'start-observer.sh'), 'utf8'); + + assert.ok(!/^\s*sleep 2\s*$/m.test(startObserverSource), 'start-observer.sh should not use the fixed `sleep 2` wait after spawning the observer loop'); + assert.ok(/\bseq 1 \d+\b/.test(startObserverSource), 'start-observer.sh should bound PID-file polling to a finite iteration count'); + assert.ok(/\[ -f "\$PID_FILE" \] && break/.test(startObserverSource), 'start-observer.sh should exit polling as soon as $PID_FILE appears'); + assert.ok(/sleep 0\.\d+/.test(startObserverSource), 'start-observer.sh should poll at sub-second intervals so healthy startups do not pay multi-second latency'); + }) + ) + passed++; + else failed++; + if (SKIP_BASH) { console.log(' ⊘ detect-project exports the resolved Python command (skipped on Windows)'); passed++;