Skip to content

Revert moving Kubernetes instructions from system prompt to skill and other improvements to evals - #2051

Merged
aantn merged 12 commits into
masterfrom
claude/investigate-evals-regression-EYQQC
May 17, 2026
Merged

aantn merged 12 commits into
masterfrom
claude/investigate-evals-regression-EYQQC

Conversation

@aantn

@aantn aantn commented May 16, 2026 •

Copy link
Copy Markdown
Collaborator

No description provided.

claude added 5 commits May 15, 2026 20:51
Adds eval 259_loki_historical_logs_pod_deleted_docker, a Kubernetes-free
sibling of 101_loki_historical_logs_pod_deleted that runs Loki in a plain
Docker container and pushes the historical log timeline via the Loki HTTP
API. Lets developers reproduce the regression locally in environments
where kind/k3s won't start (e.g. cgroup-v1 sandboxes). Verified end-to-end
with the existing OpenRouter recipe (1/1 pass, 92.4s, 25 tool calls,
$0.47).

Also fixes the classifier when MODEL_LIST_FILE_LOCATION pins a model
with the "openrouter/" litellm prefix. autoevals talks to the openai SDK
directly (not litellm), so the prefix has to be stripped before the
request; previously the call went out as model=openrouter/openai/gpt-4.1
and either hit api.openai.com with an OpenRouter key or got rejected by
OpenRouter as an invalid model id, depending on how OPENAI_BASE_URL was
set.

Signed-off-by: Claude <noreply@anthropic.com>
5 iters of eval 259_loki_historical_logs_pod_deleted_docker on each side,
opus-4.6 via OpenRouter:

  baseline cf6ddb7 (2026-04-30): 78.6s  $0.407  7.8 turns  21.8 tools  194K tk
  current  1b61fe3 (2026-05-15): 89.4s  $0.447  10.6 turns 22.0 tools  259K tk
                                 +13.7% +9.8%   +35.9%    +0.9%      +33.6%

Pass rate unchanged (5/5 vs 5/5). Tool count flat. Output tokens flat.
Total/cached input tokens up ~33-41% (z > 3.8, highly significant).
Turns up ~36% (z > 3) — same tool work, spread over more serialized rounds.
That's the signature of a bigger system prompt driving more incremental
multi-step exploration, matching the PR-#1970 hypothesis from the earlier
single-iter ci-benchmark vs master-CI comparison.

Includes the run_sweep.sh helper used to produce these numbers.

Signed-off-by: Claude <noreply@anthropic.com>
Pulled raw spans from Braintrust for test 101_loki_historical_logs_pod_deleted
on opus-4.6 — baseline run is ci-benchmark-25268492423 (cf6ddb7, May 3) and
current is master-25938985537 (1b61fe3, May 15).

Per-call prompt sizes are essentially identical (call 1: 16,826 vs 16,784).
The regression is one extra LLM call that re-sends the ~27K cached prefix.
System prompt itself is 3.2% SMALLER on current (43,248 -> 41,863 chars).

What actually changed in the prompt:
- "Whenever possible you MUST first use tools" — REMOVED
- New "Skill Usage" preamble added; Phase 1 now checks skills before TodoWrite
- The whole "If investigating Kubernetes problems" section (14 lines of
  concrete kubectl guidance) was deleted and externalised as the
  kubernetes-troubleshooting skill (PR #2040)
- User prompt grew +116% (1,008 -> 2,176 chars) with a new "# Skill Selection"
  catalog that names kubernetes-troubleshooting and tells the model to fetch
  it before investigating

Net effect: same task gets investigated in more, smaller rounds. The model
deliberates, fetches a skill, then investigates — instead of just
investigating. On the docker-loki sweep where kubectl is unavailable, the
skill fetch is wasted work and turns climb +36%.

Includes the raw baseline/current system+user prompt files and the unified
diff, so reviewers can inspect the change themselves.

Signed-off-by: Claude <noreply@anthropic.com>
Tested each suggested fix in isolation, 5 iters of the docker-loki eval
each, opus-4.6 via OpenRouter. All 20 runs passed correctness.

Means (n=5):
                    baseline  current  fix-B  fix-A
  time (s)           78.6     89.4    89.9   87.4
  turns               7.8     10.6     9.6    9.2
  total tokens     194K     259K    237K   231K
  cached input     156K     220K    198K   192K
  cost ($)         0.41     0.45    0.44   0.43
  fetch_skill log lines (Σ5) 0       29     19     10

- fix-B (restore "Whenever possible you MUST first use tools" one-liner):
  cuts turns/tokens ~10%, no wall-clock improvement.
- fix-A (restore the deleted "If investigating Kubernetes problems"
  section): cuts turns/tokens ~10–15%, cuts skill-fetch chatter ~65%.

Neither alone closes the gap. Both help in roughly the same direction.
Likely cause for the residual gap: the user-prompt "# Skill Selection"
block added by PR #2040 still names kubernetes-troubleshooting, so the
model still considers fetching the skill once per session even when the
inline guidance is back.

Suggested follow-up: combine fix-A + fix-B and gate the user-prompt
skill catalog block on actual skill relevance.

Includes raw 5×2 = 10 iter reports for both fix variants and the
side-by-side analysis in fix-comparison.md.

Signed-off-by: Claude <noreply@anthropic.com>
n=5 sweep across six candidate fixes pinpointed PR #2040 as the cause.

Fix-AD (full revert of PR #2040: restore the deleted '# If investigating
Kubernetes problems' section in generic_ask.jinja2 AND delete
holmes/plugins/skills/builtin/kubernetes-troubleshooting/) restores
baseline behavior:

  metric         baseline   current   fix-AD   recovery
  time            78.6s      89.4s    83.0s    0.59
  turns            7.8       10.6      8.6     0.71
  total tokens   194K       259K     203K     0.86
  cached         156K       220K     166K     0.85
  cost          $0.41      $0.45    $0.40    fully (slightly cheaper than baseline)
  fetch_skill (Σ5) 0          29       0      —

z-score vs baseline drops from 5.11 (turns) on current to 1.79 on
fix-AD — i.e. inside the noise floor. Per-iter spread on fix-AD sits
entirely inside the baseline range, no outliers.

Per-iter inspection showed the smoking gun: every post-#2040 iter
called fetch_skill exactly once on turn 1 (pulling the
kubernetes-troubleshooting skill). Baseline had zero such calls
because the skill simply didn't exist. The user-prompt skill catalog
block was identical between baseline and current, but only renders
content when a skill is loaded — PR #2040 was what loaded one.

Fix-A alone (prompt section only) recovered ~45% because the skill
file still existed and still got listed. Fix-B (restoring the 'MUST
use tools' one-liner from PR #1970) didn't help at all. Fix-AB and
fix-AC were equivalent to fix-A. Only fix-AD closes the gap.

The recommended PR diff is in analysis/2026-05-15-regression/the-fix.md.
Raw 5-iter reports for all six conditions are committed alongside.

Signed-off-by: Claude <noreply@anthropic.com>

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review to trigger a review and subscribe this PR to future pushes, or @claude review once for a one-time review.

Tip: disable this comment in your organization's Code Review settings.

@github-actions

github-actions Bot commented May 16, 2026 •

Copy link
Copy Markdown
Contributor

📂 Previous Runs

📜 #2 · Run @ __00a888e__ (#25965971118) — May 16, 15:47 UTC

✅ Results of HolmesGPT evals

Automatically triggered by commit 00a888e on branch claude/investigate-evals-regression-EYQQC

View workflow logs

Results of HolmesGPT evals

  • ask_holmes: 11/11 test cases were successful, 0 regressions
Status Test case Time Turns Tools Cost Total tokens Input Max input Output Max output Cached Non-cached Reasoning Compactions Src
✅ 09_crashpod 44.3s 6 13 $0.3097 133,147 130,357 24,916 2,790 1,085 104,693 25,664 378 — src
✅ 101_loki_historical_logs_pod_deleted 67.3s 7 17 $0.4131 171,749 167,327 28,935 4,422 885 135,062 32,265 1,061 — src
✅ 112_find_pvcs_by_uuid 21.1s 3 5 $0.2147 61,945 60,556 22,258 1,389 782 37,802 22,754 303 — src
✅ 12_job_crashing 44.8s 7 15 $0.3334 159,211 156,488 25,516 2,723 842 128,737 27,751 206 — src
✅ 176_network_policy_blocking_traffic_no_skills 51.2s 5 13 $0.3154 112,595 109,371 25,483 3,224 818 82,790 26,581 764 — src
✅ 227_count_configmaps_per_namespace[0] 19.1s 4 9 $0.2069 76,262 75,134 20,541 1,128 594 53,662 21,472 53 — src
✅ 243_pod_names_contain_service 30.7s 4 8 $0.2351 78,970 77,115 21,698 1,855 872 54,522 22,593 250 — src
✅ 24_misconfigured_pvc 40.3s 5 14 $0.2931 108,054 105,311 24,070 2,743 1,043 79,721 25,590 241 — src
✅ 43_current_datetime_from_prompt 3.8s 1 — $0.1182 16,898 16,798 16,798 100 100 0 16,798 60 — src
✅ 51_logs_summarize_errors 20.5s 4 5 $0.2030 76,824 75,763 20,884 1,061 353 54,874 20,889 71 — src
✅ 61_exact_match_counting 10.4s 3 3 $0.1510 52,424 52,062 17,774 362 215 34,284 17,778 31 — src
Total 32.2s avg 4.5 avg 10.2 avg $2.7937 1,048,079 1,026,282 28,935 21,797 1,085 766,147 260,135 3,418 —
Benchmark Comparison Details

Master baseline: latest master-* experiment (post-merge regression eval)
Status: 11 test/model combinations loaded

Benchmark baseline: latest ci-benchmark experiment on master
Status: 147 test/model combinations loaded

Time comparison (seconds):

Test case This branch master (17h ago) Δ vs master benchmark (13d ago) Δ vs benchmark
09_crashpod (opus-4.6) 📄 44.3s — — 32.5s ↑37%
101_loki_historical_logs_pod_deleted (opus-4.6) 📄 67.3s 81.2s ↓17% 51.7s ↑30%
112_find_pvcs_by_uuid (opus-4.6) 📄 21.1s 18.5s ↑14% 18.1s ↑17%
12_job_crashing (opus-4.6) 📄 44.8s 41.4s ±0% 42.4s ±0%
176_network_policy_blocking_traffic_no_skills (opus-4.6) 📄 51.2s 43.1s ↑19% 35.7s ↑43%
227_count_configmaps_per_namespace[0] (opus-4.6) 📄 19.1s 19.3s ±0% 19.7s ±0%
243_pod_names_contain_service (opus-4.6) 📄 30.7s 34.1s ±0% 27.4s ↑12%
24_misconfigured_pvc (opus-4.6) 📄 40.3s 34.3s ↑17% 35.8s ↑13%
43_current_datetime_from_prompt (opus-4.6) 📄 3.8s 4.1s ±0% — —
51_logs_summarize_errors (opus-4.6) 📄 20.5s 22.9s ↓11% 23.1s ↓11%
61_exact_match_counting (opus-4.6) 📄 10.4s 9.5s ±0% 10.8s ±0%
Average (m=10, b=10) 30.9s 30.9s ±0% 29.7s ↑18%

Cost comparison:

Test case This branch master (17h ago) Δ vs master benchmark (13d ago) Δ vs benchmark
09_crashpod (opus-4.6) 📄 $0.3097 $0.2716 ↑14% $0.2616 ↑18%
101_loki_historical_logs_pod_deleted (opus-4.6) 📄 $0.4131 $0.4857 ↓15% $0.3371 ↑23%
112_find_pvcs_by_uuid (opus-4.6) 📄 $0.2147 $0.2053 ±0% $0.2014 ±0%
12_job_crashing (opus-4.6) 📄 $0.3334 $0.3388 ±0% $0.3076 ±0%
176_network_policy_blocking_traffic_no_skills (opus-4.6) 📄 $0.3154 $0.2944 ±0% $0.2914 ±0%
227_count_configmaps_per_namespace[0] (opus-4.6) 📄 $0.2069 $0.2035 ±0% $0.2059 ±0%
243_pod_names_contain_service (opus-4.6) 📄 $0.2351 $0.2539 ±0% $0.2280 ±0%
24_misconfigured_pvc (opus-4.6) 📄 $0.2931 $0.2656 ↑10% $0.2831 ±0%
43_current_datetime_from_prompt (opus-4.6) 📄 $0.1182 $0.1202 ±0% — —
51_logs_summarize_errors (opus-4.6) 📄 $0.2030 $0.2109 ±0% $0.2072 ±0%
61_exact_match_counting (opus-4.6) 📄 $0.1510 $0.1522 ±0% $0.1522 ±0%
Average (m=11, b=10) $0.2540 $0.2547 ±0% $0.2475 ±0%

Total tokens comparison:

Test case This branch master (17h ago) Δ vs master benchmark (13d ago) Δ vs benchmark
09_crashpod (opus-4.6) 📄 133,147 105,496 ↑26% 103,497 ↑29%
101_loki_historical_logs_pod_deleted (opus-4.6) 📄 171,749 211,614 ↓19% 138,670 ↑24%
112_find_pvcs_by_uuid (opus-4.6) 📄 61,945 61,202 ±0% 61,169 ±0%
12_job_crashing (opus-4.6) 📄 159,211 150,381 ±0% 133,893 ↑19%
176_network_policy_blocking_traffic_no_skills (opus-4.6) 📄 112,595 108,107 ±0% 111,145 ±0%
227_count_configmaps_per_namespace[0] (opus-4.6) 📄 76,262 76,859 ±0% 76,945 ±0%
243_pod_names_contain_service (opus-4.6) 📄 78,970 82,320 ±0% 79,525 ±0%
24_misconfigured_pvc (opus-4.6) 📄 108,054 103,148 ±0% 108,047 ±0%
43_current_datetime_from_prompt (opus-4.6) 📄 16,898 17,075 ±0% — —
51_logs_summarize_errors (opus-4.6) 📄 76,824 78,273 ±0% 77,707 ±0%
61_exact_match_counting (opus-4.6) 📄 52,424 52,847 ±0% 52,942 ±0%
Average (m=11, b=10) 95,280 95,211 ±0% 94,354 ±0%

Cached tokens comparison:

Test case This branch master (17h ago) Δ vs master benchmark (13d ago) Δ vs benchmark
09_crashpod (opus-4.6) 📄 104,693 78,926 ↑33% 77,391 ↑35%
101_loki_historical_logs_pod_deleted (opus-4.6) 📄 135,062 169,448 ↓20% 106,565 ↑27%
112_find_pvcs_by_uuid (opus-4.6) 📄 37,802 37,869 ±0% 38,002 ±0%
12_job_crashing (opus-4.6) 📄 128,737 118,280 ±0% 104,761 ↑23%
176_network_policy_blocking_traffic_no_skills (opus-4.6) 📄 82,790 79,686 ±0% 81,519 ±0%
227_count_configmaps_per_namespace[0] (opus-4.6) 📄 53,662 55,029 ±0% 54,503 ±0%
243_pod_names_contain_service (opus-4.6) 📄 54,522 56,295 ±0% 55,513 ±0%
24_misconfigured_pvc (opus-4.6) 📄 79,721 76,928 ±0% 80,270 ±0%
43_current_datetime_from_prompt (opus-4.6) 📄 — — — — —
51_logs_summarize_errors (opus-4.6) 📄 54,874 55,680 ±0% 55,443 ±0%
61_exact_match_counting (opus-4.6) 📄 34,284 34,567 ±0% 34,632 ±0%
Average (m=10, b=10) 76,615 76,271 ±0% 68,860 ↑11%

Turns comparison:

Test case This branch master (17h ago) Δ vs master benchmark (13d ago) Δ vs benchmark
09_crashpod (opus-4.6) 📄 6 5 ↑20% — —
101_loki_historical_logs_pod_deleted (opus-4.6) 📄 7 8 ↓12% — —
112_find_pvcs_by_uuid (opus-4.6) 📄 3 3 ±0% — —
12_job_crashing (opus-4.6) 📄 7 6 ↑17% — —
176_network_policy_blocking_traffic_no_skills (opus-4.6) 📄 5 5 ±0% — —
227_count_configmaps_per_namespace[0] (opus-4.6) 📄 4 4 ±0% — —
243_pod_names_contain_service (opus-4.6) 📄 4 4 ±0% — —
24_misconfigured_pvc (opus-4.6) 📄 5 5 ±0% — —
43_current_datetime_from_prompt (opus-4.6) 📄 1 1 ±0% — —
51_logs_summarize_errors (opus-4.6) 📄 4 4 ±0% — —
61_exact_match_counting (opus-4.6) 📄 3 3 ±0% — —
Average (m=11, b=0) 4.5 4.4 ±0% — —

Tool calls comparison:

Test case This branch master (17h ago) Δ vs master benchmark (13d ago) Δ vs benchmark
09_crashpod (opus-4.6) 📄 13 10 ↑30% 10 ↑30%
101_loki_historical_logs_pod_deleted (opus-4.6) 📄 17 22 ↓23% 14 ↑21%
112_find_pvcs_by_uuid (opus-4.6) 📄 5 4 ↑25% 4 ↑25%
12_job_crashing (opus-4.6) 📄 15 13 ↑15% 14 ±0%
176_network_policy_blocking_traffic_no_skills (opus-4.6) 📄 13 12 ±0% 13 ±0%
227_count_configmaps_per_namespace[0] (opus-4.6) 📄 9 9 ±0% 9 ±0%
243_pod_names_contain_service (opus-4.6) 📄 8 10 ↓20% 8 ±0%
24_misconfigured_pvc (opus-4.6) 📄 14 11 ↑27% 14 ±0%
43_current_datetime_from_prompt (opus-4.6) 📄 — — — — —
51_logs_summarize_errors (opus-4.6) 📄 5 5 ±0% 5 ±0%
61_exact_match_counting (opus-4.6) 📄 3 3 ±0% 3 ±0%
Average (m=10, b=10) 10.2 9.9 ±0% 9.4 ±0%

Comparison indicators:

  • ±0% — diff under 10% (within noise threshold)
  • ↑N%/↓N% — diff 10-25%
  • ↑N%/↓N% — diff over 25% (significant)
⚠️ 1 older run truncated

Older runs were omitted to stay under GitHub's 64KB comment size limit.


✅ Results of HolmesGPT evals

Automatically triggered by commit 6cb0e8e on branch claude/investigate-evals-regression-EYQQC

View workflow logs

Results of HolmesGPT evals

  • ask_holmes: 11/11 test cases were successful, 0 regressions
Status Test case Time Turns Tools Cost Total tokens Input Max input Output Max output Cached Non-cached Reasoning Compactions Src
✅ 09_crashpod 39.5s 6 12 $0.2981 131,561 129,027 24,435 2,534 1,060 104,012 25,015 294 — src
✅ 101_loki_historical_logs_pod_deleted 81.4s 8 19 $0.4834 210,796 205,276 31,620 5,520 1,001 169,870 35,406 1,414 — src
✅ 112_find_pvcs_by_uuid 19.2s 3 4 $0.2041 60,784 59,602 21,747 1,182 613 37,597 22,005 292 — src
✅ 12_job_crashing 43.8s 6 14 $0.3172 135,211 132,402 25,633 2,809 606 105,768 26,634 203 — src
✅ 176_network_policy_blocking_traffic_no_skills 51.2s 6 14 $0.3588 143,732 140,479 28,138 3,253 749 109,484 30,995 647 — src
✅ 227_count_configmaps_per_namespace[0] 19.5s 4 9 $0.2068 76,266 75,140 20,545 1,126 594 53,669 21,471 53 — src
✅ 243_pod_names_contain_service 35.6s 5 9 $0.2600 101,960 99,839 22,423 2,121 908 76,417 23,422 261 — src
✅ 24_misconfigured_pvc 45.4s 6 15 $0.3314 135,135 131,974 25,492 3,161 1,132 104,340 27,634 534 — src
✅ 43_current_datetime_from_prompt 3.6s 1 — $0.1183 16,900 16,798 16,798 102 102 0 16,798 61 — src
✅ 51_logs_summarize_errors 20.4s 4 5 $0.2012 76,150 75,056 20,529 1,094 383 54,522 20,534 73 — src
✅ 61_exact_match_counting 10.2s 3 3 $0.1511 52,426 52,063 17,775 363 216 34,284 17,779 32 — src
Total 33.6s avg 4.7 avg 10.4 avg $2.9304 1,140,921 1,117,656 31,620 23,265 1,132 849,963 267,693 3,864 —
Benchmark Comparison Details

Master baseline: latest master-* experiment (post-merge regression eval)
Status: 11 test/model combinations loaded

Benchmark baseline: latest ci-benchmark experiment on master
Status: 147 test/model combinations loaded

Time comparison (seconds):

Test case This branch master (18h ago) Δ vs master benchmark (13d ago) Δ vs benchmark
09_crashpod (opus-4.6) 📄 39.5s — — 32.5s ↑22%
101_loki_historical_logs_pod_deleted (opus-4.6) 📄 81.4s 81.2s ±0% 51.7s ↑58%
112_find_pvcs_by_uuid (opus-4.6) 📄 19.2s 18.5s ±0% 18.1s ±0%
12_job_crashing (opus-4.6) 📄 43.8s 41.4s ±0% 42.4s ±0%
176_network_policy_blocking_traffic_no_skills (opus-4.6) 📄 51.2s 43.1s ↑19% 35.7s ↑43%
227_count_configmaps_per_namespace[0] (opus-4.6) 📄 19.5s 19.3s ±0% 19.7s ±0%
243_pod_names_contain_service (opus-4.6) 📄 35.6s 34.1s ±0% 27.4s ↑30%
24_misconfigured_pvc (opus-4.6) 📄 45.4s 34.3s ↑32% 35.8s ↑27%
43_current_datetime_from_prompt (opus-4.6) 📄 3.6s 4.1s ↓12% — —
51_logs_summarize_errors (opus-4.6) 📄 20.4s 22.9s ↓11% 23.1s ↓11%
61_exact_match_counting (opus-4.6) 📄 10.2s 9.5s ±0% 10.8s ±0%
Total (all, n=11) 33.6s 30.9s — 29.7s —
Comparable (m=10, b=10) 33.0s 30.9s ±0% 29.7s ↑23%

Cost comparison:

Test case This branch master (18h ago) Δ vs master benchmark (13d ago) Δ vs benchmark
09_crashpod (opus-4.6) 📄 $0.2981 $0.2716 ±0% $0.2616 ↑14%
101_loki_historical_logs_pod_deleted (opus-4.6) 📄 $0.4834 $0.4857 ±0% $0.3371 ↑43%
112_find_pvcs_by_uuid (opus-4.6) 📄 $0.2041 $0.2053 ±0% $0.2014 ±0%
12_job_crashing (opus-4.6) 📄 $0.3172 $0.3388 ±0% $0.3076 ±0%
176_network_policy_blocking_traffic_no_skills (opus-4.6) 📄 $0.3588 $0.2944 ↑22% $0.2914 ↑23%
227_count_configmaps_per_namespace[0] (opus-4.6) 📄 $0.2068 $0.2035 ±0% $0.2059 ±0%
243_pod_names_contain_service (opus-4.6) 📄 $0.2600 $0.2539 ±0% $0.2280 ↑14%
24_misconfigured_pvc (opus-4.6) 📄 $0.3314 $0.2656 ↑25% $0.2831 ↑17%
43_current_datetime_from_prompt (opus-4.6) 📄 $0.1183 $0.1202 ±0% — —
51_logs_summarize_errors (opus-4.6) 📄 $0.2012 $0.2109 ±0% $0.2072 ±0%
61_exact_match_counting (opus-4.6) 📄 $0.1511 $0.1522 ±0% $0.1522 ±0%
Total (all, n=11) $0.2664 $0.2547 — $0.2475 —
Comparable (m=11, b=10) $0.2664 $0.2547 ±0% $0.2475 ↑14%

Total tokens comparison:

Test case This branch master (18h ago) Δ vs master benchmark (13d ago) Δ vs benchmark
09_crashpod (opus-4.6) 📄 131,561 105,496 ↑25% 103,497 ↑27%
101_loki_historical_logs_pod_deleted (opus-4.6) 📄 210,796 211,614 ±0% 138,670 ↑52%
112_find_pvcs_by_uuid (opus-4.6) 📄 60,784 61,202 ±0% 61,169 ±0%
12_job_crashing (opus-4.6) 📄 135,211 150,381 ↓10% 133,893 ±0%
176_network_policy_blocking_traffic_no_skills (opus-4.6) 📄 143,732 108,107 ↑33% 111,145 ↑29%
227_count_configmaps_per_namespace[0] (opus-4.6) 📄 76,266 76,859 ±0% 76,945 ±0%
243_pod_names_contain_service (opus-4.6) 📄 101,960 82,320 ↑24% 79,525 ↑28%
24_misconfigured_pvc (opus-4.6) 📄 135,135 103,148 ↑31% 108,047 ↑25%
43_current_datetime_from_prompt (opus-4.6) 📄 16,900 17,075 ±0% — —
51_logs_summarize_errors (opus-4.6) 📄 76,150 78,273 ±0% 77,707 ±0%
61_exact_match_counting (opus-4.6) 📄 52,426 52,847 ±0% 52,942 ±0%
Total (all, n=11) 103,720 95,211 — 94,354 —
Comparable (m=11, b=10) 103,720 95,211 ±0% 94,354 ↑19%

Cached tokens comparison:

Test case This branch master (18h ago) Δ vs master benchmark (13d ago) Δ vs benchmark
09_crashpod (opus-4.6) 📄 104,012 78,926 ↑32% 77,391 ↑34%
101_loki_historical_logs_pod_deleted (opus-4.6) 📄 169,870 169,448 ±0% 106,565 ↑59%
112_find_pvcs_by_uuid (opus-4.6) 📄 37,597 37,869 ±0% 38,002 ±0%
12_job_crashing (opus-4.6) 📄 105,768 118,280 ↓11% 104,761 ±0%
176_network_policy_blocking_traffic_no_skills (opus-4.6) 📄 109,484 79,686 ↑37% 81,519 ↑34%
227_count_configmaps_per_namespace[0] (opus-4.6) 📄 53,669 55,029 ±0% 54,503 ±0%
243_pod_names_contain_service (opus-4.6) 📄 76,417 56,295 ↑36% 55,513 ↑38%
24_misconfigured_pvc (opus-4.6) 📄 104,340 76,928 ↑36% 80,270 ↑30%
43_current_datetime_from_prompt (opus-4.6) 📄 — — — — —
51_logs_summarize_errors (opus-4.6) 📄 54,522 55,680 ±0% 55,443 ±0%
61_exact_match_counting (opus-4.6) 📄 34,284 34,567 ±0% 34,632 ±0%
Total (all, n=11) 77,269 69,337 — 68,860 —
Comparable (m=10, b=10) 84,996 76,271 ↑11% 68,860 ↑23%

Turns comparison:

Test case This branch master (18h ago) Δ vs master benchmark (13d ago) Δ vs benchmark
09_crashpod (opus-4.6) 📄 6 5 ↑20% — —
101_loki_historical_logs_pod_deleted (opus-4.6) 📄 8 8 ±0% — —
112_find_pvcs_by_uuid (opus-4.6) 📄 3 3 ±0% — —
12_job_crashing (opus-4.6) 📄 6 6 ±0% — —
176_network_policy_blocking_traffic_no_skills (opus-4.6) 📄 6 5 ↑20% — —
227_count_configmaps_per_namespace[0] (opus-4.6) 📄 4 4 ±0% — —
243_pod_names_contain_service (opus-4.6) 📄 5 4 ↑25% — —
24_misconfigured_pvc (opus-4.6) 📄 6 5 ↑20% — —
43_current_datetime_from_prompt (opus-4.6) 📄 1 1 ±0% — —
51_logs_summarize_errors (opus-4.6) 📄 4 4 ±0% — —
61_exact_match_counting (opus-4.6) 📄 3 3 ±0% — —
Total (all, n=11) 4.7 4.4 — — —
Comparable (m=11, b=0) 4.7 4.4 ±0% — —

Tool calls comparison:

Test case This branch master (18h ago) Δ vs master benchmark (13d ago) Δ vs benchmark
09_crashpod (opus-4.6) 📄 12 10 ↑20% 10 ↑20%
101_loki_historical_logs_pod_deleted (opus-4.6) 📄 19 22 ↓14% 14 ↑36%
112_find_pvcs_by_uuid (opus-4.6) 📄 4 4 ±0% 4 ±0%
12_job_crashing (opus-4.6) 📄 14 13 ±0% 14 ±0%
176_network_policy_blocking_traffic_no_skills (opus-4.6) 📄 14 12 ↑17% 13 ±0%
227_count_configmaps_per_namespace[0] (opus-4.6) 📄 9 9 ±0% 9 ±0%
243_pod_names_contain_service (opus-4.6) 📄 9 10 ↓10% 8 ↑12%
24_misconfigured_pvc (opus-4.6) 📄 15 11 ↑36% 14 ±0%
43_current_datetime_from_prompt (opus-4.6) 📄 — — — — —
51_logs_summarize_errors (opus-4.6) 📄 5 5 ±0% 5 ±0%
61_exact_match_counting (opus-4.6) 📄 3 3 ±0% 3 ±0%
Total (all, n=11) 9.5 9.9 — 9.4 —
Comparable (m=10, b=10) 10.4 9.9 ±0% 9.4 ↑11%

Comparison indicators:

  • ±0% — diff under 10% (within noise threshold)
  • ↑N%/↓N% — diff 10-25%
  • ↑N%/↓N% — diff over 25% (significant)
📖 Legend
Icon Meaning
✅ The test was successful
➖ The test was skipped
⚠️ The test failed but is known to be flaky or known to fail
🚧 The test had a setup failure (not a code regression)
🔧 The test failed due to mock data issues (not a code regression)
🚫 The test was throttled by API rate limits/overload
❌ The test failed and should be fixed before merging the PR
🔄 Re-run evals manually

⚠️ Warning: /eval comments always run using the workflow from master, not from this PR branch. If you modified the GitHub Action (e.g., added secrets or env vars), those changes won't take effect.

To test workflow changes, use the GitHub CLI or Actions UI instead:

gh workflow run eval-regression.yaml --repo HolmesGPT/holmesgpt --ref claude/investigate-evals-regression-EYQQC -f markers=regression -f filter=

Option 1: Comment on this PR with /eval:

/eval
tags: regression

Or with more options (one per line):

/eval
model: gpt-4o
tags: regression
id: 09_crashpod
iterations: 5

Run evals on a different branch (e.g., master) for comparison:

/eval
branch: master
tags: regression
Option Description
model Model(s) to test (default: same as automatic runs)
tags Pytest tags / markers (no default - runs all tests!)
id Eval ID / pytest -k filter (use /list to see valid eval names)
iterations Number of runs, max 10
branch Run evals on a different branch (for cross-branch comparison)

Quick re-run: Use /rerun to re-run the most recent /eval on this PR with the same parameters.

Option 2: Trigger via GitHub Actions UI → "Run workflow"

Option 3: Add PR labels to include extra evals (applies to both automatic runs and /eval comments):

Label Effect
evals-tag-<name> Run tests with tag <name> alongside regression
evals-id-<name> Run a specific eval by test ID
evals-model-<name> Override the model (use model list name, e.g. sonnet-4.5)

Examples: evals-tag-easy, evals-id-09_crashpod, evals-model-sonnet-4.5

🏷️ Valid tags

benchmark, chain-of-causation, compaction, confluence, context_window, conversation_worker, coralogix, counting, database, datadog, datetime, db-connectors, easy, elasticsearch, embeds, fast, frontend, grafana, hard, images, integration, kafka, kubernetes, leaked-information, logs, loki, manual, mcp, medium, metrics, network, newrelic, no-cicd, numerical, one-test, port-forward, prometheus, question-answer, regression, skills, slackbot, storage, token-limit, toolset-limitation, traces, transparency, victorialogs

🤖 Valid models

deepseek-chat, deepseek-r1-reasoner, deepseek-reasoner, deepseek-v3.2-chat, gemini-3-flash-preview, gemini-3-pro-preview, gemini-3.1-pro-preview, gpt-4.1, gpt-5.2-high-reasoning, gpt-5.3-codex, gpt-5.4, haiku-4.5, kimi-2.5, kimi-2.5-openrouter, opus-4.5, opus-4.6, opus-4.7, qwen-next-80B-instruct, qwen-next-80B-thinking, sonnet-4.5, sonnet-4.6


Commands: /eval · /rerun · /list

CLI: gh workflow run eval-regression.yaml --repo HolmesGPT/holmesgpt --ref claude/investigate-evals-regression-EYQQC -f markers=regression -f filter=

@coderabbitai

coderabbitai Bot commented May 16, 2026 •

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds a Docker-based Loki test fixture with a log generator and orchestration, inserts Kubernetes troubleshooting guidance into the generic prompt, detects OpenRouter-prefixed classifier models in the model-list path, and adds eval-regression diagnostic documentation.

Changes

Loki Docker Test Fixture for Pod Deleted Scenario

Layer / File(s) Summary
Historical log generation and HTTP push
tests/llm/fixtures/.../generate_logs.py
Script defines constants for service/pod identity, a push() function grouping logs by level and sending them to Loki, a log_entry() helper for building log records with fixed fields, a generate() function simulating multi-day logs with random INFO and a time-bounded ERROR incident, and a __main__ entrypoint reading the Loki URL from argv.
Loki configuration and test orchestration
tests/llm/fixtures/.../loki-config.yaml, test_case.yaml, toolsets.yaml
Loki server fixture config (in-memory ring, storage dirs, schema), toolset mapping enabling grafana/loki and disabling Kubernetes toolsets, test metadata and before_test orchestration (start/remove container, wait for /ready, ingest logs via generator, poll loki/api/v1/query_range for ERROR logs), and after_test teardown removing the container.

Kubernetes Troubleshooting Guidance Enhancement

Layer / File(s) Summary
Kubernetes investigation guidance
holmes/plugins/prompts/generic_ask.jinja2
Adds a new "If investigating Kubernetes problems" section instructing when to run kubectl_describe, how to fetch pod logs for crashing pods, guidance on checking related objects (workload → controller → pod), and constraints on phrasing answers for pending pods, selector/affinity mismatches, and transient runtime issues.

OpenRouter Classifier Model Support

Layer / File(s) Summary
OpenRouter provider prefix handling
tests/llm/utils/classifiers.py
When the model list exists, detect classifier models prefixed with openrouter/, strip that prefix for OpenAI SDK calls, and set the client base URL to OPENROUTER_API_BASE (or a default OpenRouter endpoint) if the model list did not supply one.

Eval Regression Diagnostic Documentation

Layer / File(s) Summary
Investigating Eval Regressions / Holmes Behavior Changes
CLAUDE.md
Adds a new guidance section prescribing rules and a step-by-step diagnostic workflow for comparing baseline vs current eval runs using traces, comparing per-iteration tool-call shapes, and inspecting suspect PR diffs during bisecting.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • Sheeproid
  • arikalon1
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title accurately describes the main changes: reverting Kubernetes instructions from system prompt to skill and mentioning other improvements, which aligns with restoring the removed guidance section and removing the skill directory.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented May 16, 2026 •

Copy link
Copy Markdown
Contributor

✅ Docker images ready for b35d71ea (built in 57s)

⚠️ Warning: does not support ARM (ARM images are built on release only - not on every PR)

Use these tags to pull the images for testing.

📋 Copy commands

⚠️ Temporary images are deleted after 30 days. Copy to a permanent registry before using them:

gcloud auth configure-docker us-central1-docker.pkg.dev
docker pull us-central1-docker.pkg.dev/robusta-development/temporary-builds/holmes:b35d71ea
docker tag us-central1-docker.pkg.dev/robusta-development/temporary-builds/holmes:b35d71ea me-west1-docker.pkg.dev/robusta-development/development/holmes-dev:b35d71ea
docker push me-west1-docker.pkg.dev/robusta-development/development/holmes-dev:b35d71ea
docker pull us-central1-docker.pkg.dev/robusta-development/temporary-builds/holmes-operator:b35d71ea
docker tag us-central1-docker.pkg.dev/robusta-development/temporary-builds/holmes-operator:b35d71ea me-west1-docker.pkg.dev/robusta-development/development/holmes-operator-dev:b35d71ea
docker push me-west1-docker.pkg.dev/robusta-development/development/holmes-operator-dev:b35d71ea

Patch Helm values in one line (choose the chart you use):

HolmesGPT chart:

helm upgrade --install holmesgpt ./helm/holmes \
  --set registry=me-west1-docker.pkg.dev/robusta-development/development \
  --set image=holmes-dev:b35d71ea \
  --set operator.registry=me-west1-docker.pkg.dev/robusta-development/development \
  --set operator.image=holmes-operator-dev:b35d71ea

Robusta wrapper chart:

helm upgrade --install robusta robusta/robusta \
  --reuse-values \
  --set holmes.registry=me-west1-docker.pkg.dev/robusta-development/development \
  --set holmes.image=holmes-dev:b35d71ea \
  --set holmes.operator.registry=me-west1-docker.pkg.dev/robusta-development/development \
  --set holmes.operator.image=holmes-operator-dev:b35d71ea

@netlify

netlify Bot commented May 16, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for holmes-docs ready!

Name Link
🔨 Latest commit 6cb0e8e
🔍 Latest deploy log https://app.netlify.com/projects/holmes-docs/deploys/6a08929d4262be00099eb8b4
😎 Deploy Preview https://deploy-preview-2051--holmes-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

- Restore the "# If investigating Kubernetes problems" section to
  generic_ask.jinja2 that was removed in PR #2040
- Delete holmes/plugins/skills/builtin/kubernetes-troubleshooting/
  so the skill no longer registers in the catalog
- Drop the regression and no-cicd tags from the new docker-loki eval
  (test 259); keep logs/easy/loki/fast
- Remove the analysis/ directory used during the investigation

Sweep numbers (n=5, opus-4.6, docker-loki eval, 259):

  metric         baseline   current   this PR   recovery
  time            78.6s      89.4s    83.0s    0.59
  turns            7.8       10.6      8.6     0.71
  total tokens   194K       259K     203K     0.86
  cached         156K       220K     166K     0.85
  cost          $0.41      $0.45    $0.40    fully restored
  fetch_skill (Σ5)  0         29       0      —

Signed-off-by: Claude <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (3)
analysis/2026-05-15-regression/the-fix.md (1)

71-92: ⚡ Quick win

Add language identifier to fenced code block.

The code block should specify diff as the language identifier for proper syntax highlighting.

📝 Proposed fix
-```
+```diff
 # 1. Add back the deleted section to generic_ask.jinja2 (between the
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@analysis/2026-05-15-regression/the-fix.md` around lines 71 - 92, The fenced
code block in the PR description is missing the language identifier for proper
syntax highlighting; update the block around the changes to include the "diff"
language tag so the added section for generic_ask.jinja2 and the removal
instruction for holmes/plugins/skills/builtin/kubernetes-troubleshooting render
correctly (refer to the added comments mentioning kubectl commands,
kubectl_describe and the file generic_ask.jinja2 as well as the remove command
for the kubernetes-troubleshooting skill).
analysis/2026-05-15-regression/fix_a_k8s_section_iter_1.md (1)

15-17: ⚡ Quick win

Pin baseline reference to a commit SHA (or dated run ID).

Line 15’s “latest ci-benchmark experiment on master” is mutable over time. Use a concrete SHA/date so this regression artifact stays reproducible.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@analysis/2026-05-15-regression/fix_a_k8s_section_iter_1.md` around lines 15 -
17, Replace the mutable text "Baseline: latest ci-benchmark experiment on
master" with a concrete, pinned reference (e.g., a commit SHA or a dated run ID)
so the regression artifact is reproducible; locate the exact line containing the
phrase "Baseline: latest ci-benchmark experiment on master" in the file and
update it to include the chosen immutable identifier (for example "Baseline:
<commit-SHA> (run date: YYYY-MM-DD)" or "Baseline: <dated-run-ID>") and, if
appropriate, add a brief parenthetical explaining the chosen identifier.
analysis/2026-05-15-regression/fix-comparison.md (1)

3-3: 💤 Low value

Consider using recommended model naming format for future regression tests.

The model reference "opus-4.6 via OpenRouter" documents the actual test that was run. For future regression tests, consider using the recommended naming format (e.g., anthropic/claude-opus-4-5-20251101) for consistency and clarity. As per coding guidelines, documentation examples should reference models using the provider-prefixed format with date suffixes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@analysis/2026-05-15-regression/fix-comparison.md` at line 3, The test
documentation uses an informal model reference "opus-4.6 via OpenRouter"; update
the test name/description to use the provider-prefixed, dated model naming
convention (e.g., replace "opus-4.6 via OpenRouter" with a provider-prefixed
form like "anthropic/claude-opus-4-6-<YYYYMMDD>" or the exact published tag),
ensuring the string in the test identifier
`259_loki_historical_logs_pod_deleted_docker` and any accompanying description
uses the canonical format for consistency with other regression tests and
guidelines.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@analysis/2026-05-15-regression/n5-sweep.md`:
- Around line 12-24: The markdown tables under the "Baseline (`cf6ddb7`)" and
"Current (`1b61fe3`)" headings need blank lines inserted before and after each
table to satisfy markdownlint MD058; update the n5-sweep.md content by ensuring
there's an empty line between the headings and the table start, and another
empty line after the table end (i.e., add a blank line before the |--- row and
after the last | row for both tables).

In `@analysis/2026-05-15-regression/run_sweep.sh`:
- Around line 22-33: The script run_sweep.sh currently silences pytest failures
by appending "|| true" to the timeout/poetry pytest command, causing failed
iterations to be treated as success; remove "|| true" and instead capture the
pytest exit code from the timeout/poetry invocation (e.g., store "$?"/assign to
a variable immediately after the timeout poetry run pytest line) and propagate
failures by exiting non-zero (exit with that code) or set a failure flag and
exit non-zero at the end; ensure the test invocation and subsequent
evals_report.md handling still run when desired but that any pytest non-zero
exit causes the script to fail (reference the timeout 300 poetry run pytest ...
command and the surrounding conditional that checks evals_report.md).

In
`@tests/llm/fixtures/test_ask_holmes/259_loki_historical_logs_pod_deleted_docker/generate_logs.py`:
- Around line 20-22: Replace the hardcoded shared values by generating
test-specific resource names for fixture 259: update the constants NAMESPACE,
POD_NAME and SERVICE in generate_logs.py to use the test id (e.g. "app-259" and
"payment-api-259-<unique-suffix>") instead of "app-101"/"payment-api-101-*",
ensuring POD_NAME includes a unique per-test suffix; then update the
corresponding namespace and resource name references inside test_case.yaml
(queries/prompts) to match the new app-259 and payment-api-259 names so the
fixture and its test_case remain consistent and isolated.

In
`@tests/llm/fixtures/test_ask_holmes/259_loki_historical_logs_pod_deleted_docker/test_case.yaml`:
- Around line 1-16: The test oracle is too vague and can pass without querying
Loki; update the YAML by making expected_output assert a discoverable log detail
(e.g., the exact incident message substring and a tight time window like
"2025-08-02T13:45:00Z" or the log line "error: connection pool exhausted") so
only a real Loki response satisfies it, and enable tool-call verification by
adding include_tool_calls: true so the test harness can verify the grafana/loki
tool was invoked; adjust user_prompt only if needed to reference the exact
timestamp string used in expected_output.

---

Nitpick comments:
In `@analysis/2026-05-15-regression/fix_a_k8s_section_iter_1.md`:
- Around line 15-17: Replace the mutable text "Baseline: latest ci-benchmark
experiment on master" with a concrete, pinned reference (e.g., a commit SHA or a
dated run ID) so the regression artifact is reproducible; locate the exact line
containing the phrase "Baseline: latest ci-benchmark experiment on master" in
the file and update it to include the chosen immutable identifier (for example
"Baseline: <commit-SHA> (run date: YYYY-MM-DD)" or "Baseline: <dated-run-ID>")
and, if appropriate, add a brief parenthetical explaining the chosen identifier.

In `@analysis/2026-05-15-regression/fix-comparison.md`:
- Line 3: The test documentation uses an informal model reference "opus-4.6 via
OpenRouter"; update the test name/description to use the provider-prefixed,
dated model naming convention (e.g., replace "opus-4.6 via OpenRouter" with a
provider-prefixed form like "anthropic/claude-opus-4-6-<YYYYMMDD>" or the exact
published tag), ensuring the string in the test identifier
`259_loki_historical_logs_pod_deleted_docker` and any accompanying description
uses the canonical format for consistency with other regression tests and
guidelines.

In `@analysis/2026-05-15-regression/the-fix.md`:
- Around line 71-92: The fenced code block in the PR description is missing the
language identifier for proper syntax highlighting; update the block around the
changes to include the "diff" language tag so the added section for
generic_ask.jinja2 and the removal instruction for
holmes/plugins/skills/builtin/kubernetes-troubleshooting render correctly (refer
to the added comments mentioning kubectl commands, kubectl_describe and the file
generic_ask.jinja2 as well as the remove command for the
kubernetes-troubleshooting skill).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a6ec4951-a11a-4933-a20f-e189ca95646e

📥 Commits

Reviewing files that changed from the base of the PR and between fb303ff and 145be73.

📒 Files selected for processing (50)
  • analysis/2026-05-15-regression/baseline_iter_1.md
  • analysis/2026-05-15-regression/baseline_iter_2.md
  • analysis/2026-05-15-regression/baseline_iter_3.md
  • analysis/2026-05-15-regression/baseline_iter_4.md
  • analysis/2026-05-15-regression/baseline_iter_5.md
  • analysis/2026-05-15-regression/baseline_system_prompt.txt
  • analysis/2026-05-15-regression/baseline_user_prompt.txt
  • analysis/2026-05-15-regression/current_iter_1.md
  • analysis/2026-05-15-regression/current_iter_2.md
  • analysis/2026-05-15-regression/current_iter_3.md
  • analysis/2026-05-15-regression/current_iter_4.md
  • analysis/2026-05-15-regression/current_iter_5.md
  • analysis/2026-05-15-regression/current_system_prompt.txt
  • analysis/2026-05-15-regression/current_user_prompt.txt
  • analysis/2026-05-15-regression/fix-comparison.md
  • analysis/2026-05-15-regression/fix_a_k8s_section_iter_1.md
  • analysis/2026-05-15-regression/fix_a_k8s_section_iter_2.md
  • analysis/2026-05-15-regression/fix_a_k8s_section_iter_3.md
  • analysis/2026-05-15-regression/fix_a_k8s_section_iter_4.md
  • analysis/2026-05-15-regression/fix_a_k8s_section_iter_5.md
  • analysis/2026-05-15-regression/fix_ab_iter_1.md
  • analysis/2026-05-15-regression/fix_ab_iter_2.md
  • analysis/2026-05-15-regression/fix_ab_iter_3.md
  • analysis/2026-05-15-regression/fix_ab_iter_4.md
  • analysis/2026-05-15-regression/fix_ab_iter_5.md
  • analysis/2026-05-15-regression/fix_ac_iter_1.md
  • analysis/2026-05-15-regression/fix_ac_iter_2.md
  • analysis/2026-05-15-regression/fix_ac_iter_3.md
  • analysis/2026-05-15-regression/fix_ac_iter_4.md
  • analysis/2026-05-15-regression/fix_ac_iter_5.md
  • analysis/2026-05-15-regression/fix_ad_iter_1.md
  • analysis/2026-05-15-regression/fix_ad_iter_2.md
  • analysis/2026-05-15-regression/fix_ad_iter_3.md
  • analysis/2026-05-15-regression/fix_ad_iter_4.md
  • analysis/2026-05-15-regression/fix_ad_iter_5.md
  • analysis/2026-05-15-regression/fix_b_must_use_tools_iter_1.md
  • analysis/2026-05-15-regression/fix_b_must_use_tools_iter_2.md
  • analysis/2026-05-15-regression/fix_b_must_use_tools_iter_3.md
  • analysis/2026-05-15-regression/fix_b_must_use_tools_iter_4.md
  • analysis/2026-05-15-regression/fix_b_must_use_tools_iter_5.md
  • analysis/2026-05-15-regression/n5-sweep.md
  • analysis/2026-05-15-regression/run_sweep.sh
  • analysis/2026-05-15-regression/system_prompt.diff
  • analysis/2026-05-15-regression/the-fix.md
  • analysis/2026-05-15-regression/trace-diff.md
  • tests/llm/fixtures/test_ask_holmes/259_loki_historical_logs_pod_deleted_docker/generate_logs.py
  • tests/llm/fixtures/test_ask_holmes/259_loki_historical_logs_pod_deleted_docker/loki-config.yaml
  • tests/llm/fixtures/test_ask_holmes/259_loki_historical_logs_pod_deleted_docker/test_case.yaml
  • tests/llm/fixtures/test_ask_holmes/259_loki_historical_logs_pod_deleted_docker/toolsets.yaml
  • tests/llm/utils/classifiers.py

Comment thread analysis/2026-05-15-regression/n5-sweep.md Outdated
Comment thread analysis/2026-05-15-regression/run_sweep.sh Outdated
- Rename namespace/pod to app-259 / payment-api-259-* (per CLAUDE.md:
  "Use dedicated namespace per test: app-<testid>")
- Tighten expected_output to require a discoverable log detail (time
  window + exact ERROR substring) instead of a generic conclusion that
  the model could plausibly guess
- Add include_tool_calls: true so the grader also verifies grafana/loki
  was actually called

Verified locally with the docker-loki Loki container: 1/1 pass, 86.9s,
9 turns, 20 tool calls, $0.40 (opus-4.6 via OpenRouter).

Leaving the Benchmark Master / Benchmark PR CI failures alone — both
master and PR runs failed at the same point (~100s into the job),
which means the failure is upstream of this PR (likely OpenRouter
credits exhaustion at the time of run, same env issue we hit earlier).

Signed-off-by: Claude <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@tests/llm/fixtures/test_ask_holmes/259_loki_historical_logs_pod_deleted_docker/generate_logs.py`:
- Around line 26-27: Add Python type hints to the four functions missing
annotations: push, log_entry, generate, and add. For each function signature
(the def lines for push, log_entry, generate, and add) add explicit parameter
and return types consistent with the repository conventions (e.g., str for
loki_url, typing.Dict/typing.List for streams_by_level or entries, specific
types for timestamps/levels, and appropriate return types like None or
Iterable[...]); ensure you import any typing symbols used (e.g., List, Dict,
Iterable, Optional) at the top of the file and update all four function
definitions accordingly.
- Around line 71-75: Update all function signatures to include full type hints:
add parameter and return type annotations for push(), log_entry(), and
generate(), and add a return type for the nested add() function; reference the
functions named push, log_entry, generate, and add in the file so reviewers can
find them. Make datetime objects UTC-aware by constructing them with
tzinfo=timezone.utc (or using datetime(..., tz=timezone.utc)) for problem_start,
problem_end, current, and scenario_end so subsequent .timestamp() calls are
consistent across timezones. Ensure any imports required for typing (e.g., List,
Dict, Optional) and timezone (from datetime import timezone) are added or
adjusted accordingly. Verify that type hints match the actual returned values
(e.g., Dict[str, Any] or List[str]) used in push/log_entry/generate/add.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 01c3090b-1db4-4acd-9d1f-e1c0f22e1220

📥 Commits

Reviewing files that changed from the base of the PR and between 0c37654 and d2286a9.

📒 Files selected for processing (2)
  • tests/llm/fixtures/test_ask_holmes/259_loki_historical_logs_pod_deleted_docker/generate_logs.py
  • tests/llm/fixtures/test_ask_holmes/259_loki_historical_logs_pod_deleted_docker/test_case.yaml

claude added 5 commits May 16, 2026 11:29
Codifies four rules learned the hard way while investigating the
PR #2040 eval regression:

1. Pull raw trace data BEFORE theorising from file diffs (file diffs
   misled this investigation twice — claimed prompt grew when it
   actually shrank in rendered form).
2. Compare per-iter tool-call sequences, not aggregate means
   (means hid the +1 deterministic fetch_skill turn under noise).
3. When bisecting a PR, read the FULL diff with git show --stat;
   half-reverts of just the file you noticed waste sweeps because
   the other side of the PR (registered skill, default config, etc.)
   still triggers the new behavior.
4. Deterministic 5/5 behavior needs trigger removal, not prompt
   softening — competing nudges rarely override a strong trigger
   like a registered skill in the catalog.

Includes the ordered diagnostic sequence (traces first, then sweeps).

Signed-off-by: Claude <noreply@anthropic.com>
Earlier version overgeneralized from a single investigation: the
"trigger removal vs prompt softening" rule and the fixed 5-step
diagnostic recipe both baked in the specific shape of the PR-#2040
regression (more LLM calls, deterministic skill fetch). They don't
generalize to other regression shapes.

Reduce to the actually-general principle: pull trace data before
designing a fix; look at individual runs not just aggregates; and
read the full diff of a suspect PR before reverting parts of it.

Signed-off-by: Claude <noreply@anthropic.com>
1. Prefer test_id over eval_id when building baseline rows
   (tests/llm/utils/braintrust_history.py)

   For parameterized tests like
   '227_count_configmaps_per_namespace[0][opus-4.6][default]', the eval
   metadata stores:
     - eval_id  = '227_count_configmaps_per_namespace'   (strips [N])
     - test_id  = '227_count_configmaps_per_namespace[0]' (keeps it)

   The report joins on test_case_name which always carries the
   parameterization, so eval_id-keyed baseline rows silently fail to
   match and the "vs master" / "vs benchmark" cells come back empty for
   every parameterized eval. Falling back to eval_id keeps older spans
   that only set the latter from disappearing.

   Verified end-to-end against the live master-25943210368 experiment:
   11/11 regression tests now match (was 10/11).

2. Pass GITHUB_TOKEN to the pytest step in eval-regression.yaml

   tests/llm/utils/braintrust_history.py uses
   _find_recent_workflow_run_ids() to map github action run IDs to
   Braintrust experiment names (master-{run_id}, ci-benchmark-{run_id}).
   Without GITHUB_TOKEN that call hits the 60 req/h unauthenticated
   rate limit shared across GitHub Actions runner IPs, returns no run
   IDs, and the master/benchmark baselines come back empty for the
   entire report. The function reads the token from the env when
   present (see line 174), it just wasn't being passed in.

Signed-off-by: Claude <noreply@anthropic.com>
The existing single summary row (now relabeled "Comparable") averaged
each baseline column over its own matched subset and produced
apples-to-apples deltas, but the "This branch" cell silently switched
between two different test subsets depending on which baseline was
available — which made the absolute number hard to read.

Now each metric table emits two summary rows:

- **Total (all, n=N)** — each column averaged over its own non-null
  subset across all rows. The "This branch" cell is the mean of every
  current value in the run, regardless of whether a baseline exists.
  Δ cells are intentionally empty because the per-column subsets may
  differ (e.g. baseline missing one test would make the delta compare
  different sets of tests — apples to oranges).

- **Comparable (m=N, b=N)** — per-baseline matched subsets only.
  The vs-master pair is averaged across rows where both this-branch
  AND master have a value; same for vs-benchmark. Use this row for
  meaningful deltas; use the Total row for absolutes.

Example (from PR 2051 where master had no data and benchmark was
missing two tests):

  | Total (all, n=11)   | 31.9s | —     | — | 30.8s | —      |
  | Comparable (m=0,b=9)| 36.3s | —     | — | 30.8s | ↑18%   |

The 31.9s vs 36.3s gap is informative: the two tests missing from the
benchmark happen to be short ones, so the comparable subset runs
slower on average than the full run.

Signed-off-by: Claude <noreply@anthropic.com>
@aantn aantn changed the title Add Docker-Loki regression test and analysis for skill-fetch behavior Revert moving Kubernetes instructions from system prompt to skill and other improvements to evals May 16, 2026
@aantn
aantn enabled auto-merge (squash) May 16, 2026 17:32
@aantn
aantn merged commit cf1ad52 into master May 17, 2026
19 of 22 checks passed
@aantn
aantn deleted the claude/investigate-evals-regression-EYQQC branch May 17, 2026 06:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants