diff --git a/skills/continuous-learning-v2/agents/observer-loop.sh b/skills/continuous-learning-v2/agents/observer-loop.sh index 1ac1c56c..fa50c1f6 100755 --- a/skills/continuous-learning-v2/agents/observer-loop.sh +++ b/skills/continuous-learning-v2/agents/observer-loop.sh @@ -241,11 +241,15 @@ PROMPT # on all platforms, not just when the observer happens to be launched from the project root. cd "$PROJECT_DIR" || { echo "[$(date)] Failed to cd to PROJECT_DIR ($PROJECT_DIR), skipping analysis" >> "$LOG_FILE"; rm -f "$analysis_file"; return; } - # Prevent observe.sh from recording this automated Haiku session as observations. + # Prevent observe.sh from recording this automated observer session as observations. # Pass prompt via -p flag instead of stdin redirect for Windows compatibility (#842). # prompt_content is already loaded in-memory so this no longer depends on the # mktemp absolute path continuing to resolve after cwd changes (#1296). - ECC_SKIP_OBSERVE=1 ECC_HOOK_PROFILE=minimal claude --model haiku --max-turns "$max_turns" --print \ + # Model is configurable via ECC_OBSERVER_MODEL (defaults to haiku for cost efficiency); + # e.g. ECC_OBSERVER_MODEL=opus for higher-quality instinct extraction. Heavier models are + # slower — consider raising ECC_OBSERVER_TIMEOUT_SECONDS (default 120s) so the watchdog + # doesn't kill the analysis mid-run. + ECC_SKIP_OBSERVE=1 ECC_HOOK_PROFILE=minimal claude --model "${ECC_OBSERVER_MODEL:-haiku}" --max-turns "$max_turns" --print \ --allowedTools "Read,Write" \ -p "$prompt_content" >> "$LOG_FILE" 2>&1 & claude_pid=$! diff --git a/tests/hooks/observer-memory.test.js b/tests/hooks/observer-memory.test.js index 597c7df2..9bfbdde0 100644 --- a/tests/hooks/observer-memory.test.js +++ b/tests/hooks/observer-memory.test.js @@ -454,8 +454,13 @@ test('claude invocation still includes ECC_SKIP_OBSERVE and ECC_HOOK_PROFILE gua const content = fs.readFileSync(observerLoopPath, 'utf8'); // Find the claude execution line(s) const lines = content.split('\n'); - const claudeLine = lines.find(l => l.includes('claude --model haiku')); - assert.ok(claudeLine, 'Should find claude --model haiku invocation line'); + const claudeLine = lines.find(l => l.includes('claude --model')); + assert.ok(claudeLine, 'Should find claude --model invocation line'); + // Model is configurable via ECC_OBSERVER_MODEL but must still default to haiku. + assert.ok( + claudeLine.includes('${ECC_OBSERVER_MODEL:-haiku}'), + `claude --model should default to haiku and honor ECC_OBSERVER_MODEL, got: ${claudeLine}` + ); // The env vars are on the same line as the claude command const claudeLineIndex = lines.indexOf(claudeLine); const fullCommand = lines.slice(Math.max(0, claudeLineIndex - 1), claudeLineIndex + 3).join(' ');