Skip to content

Add eval 283: CPU throttling caused by cache-key mismatch bug - #2310

Open
aantn wants to merge 2 commits into
masterfrom
claude/cpu-throttling-bug-eval-m2dev7
Open

Add eval 283: CPU throttling caused by cache-key mismatch bug#2310
aantn wants to merge 2 commits into
masterfrom
claude/cpu-throttling-bug-eval-m2dev7

Conversation

@aantn

@aantn aantn commented Jul 21, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds a new LLM evaluation test (eval 283) that validates Holmes's ability to diagnose CPU throttling caused by an application-level caching bug. The eval tests the complete investigation chain: metrics → logs → source code analysis via MCP.

Key Changes

  • Kubernetes deployment (deployment.yaml): Sets up a quote-service pod with intentional CPU throttling, a rate-sync worker to generate load, Promtail for log shipping to Loki, and a GitLab-mimicking MCP server that serves the application source code
  • Application code (app/server.py, app/tariff_engine.py, app/README.md): Implements a shipping quote service with a deliberate cache-key mismatch bug — tariff matrices are stored with key format "ORIGIN->DEST" but looked up via _cache_key() which builds "ORIGIN:DEST", causing cache misses and repeated expensive computations
  • GitLab MCP server (gitlab_mcp_server.py): Provides read-only repository access tools (list_projects, get_repository_tree, get_file_contents, list_commits) that serve the exact source files the pod executes, enabling Holmes to discover the bug by reading the code
  • Test case definition (test_case.yaml): Defines the eval scenario, expected outputs, setup/teardown, and validation needles:
    • Needle 1: Loki contains slow-function warnings (compute_tariff_matrix took NNNms)
    • Needle 2: The buggy write key (->) is present in tariff_engine.py served by MCP
    • Needle 3: Real CPU throttling metrics appear in Prometheus (cAdvisor container_cpu_cfs_throttled_periods_total)
  • Toolset configuration (toolsets.yaml): Enables Kubernetes, Loki, Prometheus, and GitLab MCP toolsets with appropriate port-forwards and API endpoints

Implementation Details

  • The cache bug is subtle: _cache_key() returns "AMS:JFK" but the code stores under "AMS->JFK", so every request recomputes the expensive tariff matrix
  • The eval requires real CPU throttling metrics from cAdvisor (via kube-prometheus-stack), not synthetic metrics
  • Promtail ships JSON logs to Loki so Holmes can discover the slow-function hint without kubectl logs
  • The MCP server reads application source from a Kubernetes Secret (same Secret the pod executes), ensuring Holmes reads the exact running code
  • Setup validates three needles before allowing the test to proceed, ensuring the scenario is properly configured
  • Generous 900s setup timeout accounts for image pulls, pip installs, and metric accumulation (cAdvisor scrapes ~30s intervals)

https://claude.ai/code/session_016LXH3dCxNQNVHbHQTqjBgj

Summary by CodeRabbit

  • New Features

    • Added a new quote-service eval fixture with /healthz and /api/v1/quote endpoints, structured JSON logging, and tariff caching/cheapest-quote selection.
    • Added a GitLab MCP server for browsing two fixed projects (repo tree, file contents, and commit history).
    • Added an end-to-end eval that validates evidence via Loki/Prometheus, plus a background rate-sync workload and supporting Kubernetes deployment components.
  • Documentation

    • Updated sandbox limitations and added explicit workarounds for failing release downloads, missing CPU metrics, and TLS issues during in-cluster installs.

New ask-holmes eval testing a full metrics -> logs -> source-code
root-cause chain:

- quote-service (namespace app-283, CPU limit 200m) recomputes an
  expensive tariff matrix on every request because cache entries are
  written under the key format ORIGIN->DEST but looked up via
  _cache_key(), which builds ORIGIN:DEST — the cache never hits, CPU
  pegs at the CFS quota, and Prometheus fires CPUThrottlingHigh.
- Loki (promtail sidecar) carries warnings that name only the slow
  function (compute_tariff_matrix took NNNNms), not the cause.
- A GitLab-mimicking MCP server (FastMCP, streamable-http) exposes
  list_projects / get_repository_tree / get_file_contents /
  list_commits, serving the exact source files the pod runs (both
  mount the same Secret), plus a commit history whose latest entry is
  the refactor that introduced the bug.

The expected root cause (the mismatched key formats in
tariff_engine.py) can only be produced by reading the code, ruling out
hallucination. Verified end-to-end in the sandbox: setup needles all
pass and opus-4.6 (via OpenRouter) finds the exact bug and the
offending commit, 1/1.

Also document three new Claude Code sandbox limitations discovered
while verifying (GitHub release downloads blocked, CFS quota not
enforced, pip TLS MITM inside pods) in CLAUDE.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016LXH3dCxNQNVHbHQTqjBgj
Signed-off-by: Claude <noreply@anthropic.com>

@claude claude Bot left a comment

Copy link
Copy Markdown

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 for a one-time review, or @claude review always to subscribe this PR to a review on every future push.

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

@github-actions

github-actions Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Docker images ready for 5b0334e05 (built in 1m 9s)

⚠️ 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:5b0334e05
docker tag us-central1-docker.pkg.dev/robusta-development/temporary-builds/holmes:5b0334e05 me-west1-docker.pkg.dev/robusta-development/development/holmes-dev:5b0334e05
docker push me-west1-docker.pkg.dev/robusta-development/development/holmes-dev:5b0334e05
docker pull us-central1-docker.pkg.dev/robusta-development/temporary-builds/holmes-operator:5b0334e05
docker tag us-central1-docker.pkg.dev/robusta-development/temporary-builds/holmes-operator:5b0334e05 me-west1-docker.pkg.dev/robusta-development/development/holmes-operator-dev:5b0334e05
docker push me-west1-docker.pkg.dev/robusta-development/development/holmes-operator-dev:5b0334e05

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:5b0334e05 \
  --set operator.registry=me-west1-docker.pkg.dev/robusta-development/development \
  --set operator.image=holmes-operator-dev:5b0334e05

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:5b0334e05 \
  --set holmes.operator.registry=me-west1-docker.pkg.dev/robusta-development/development \
  --set holmes.operator.image=holmes-operator-dev:5b0334e05

@netlify

netlify Bot commented Jul 21, 2026

Copy link
Copy Markdown

Deploy Preview for holmes-docs ready!

Name Link
🔨 Latest commit fb2a664
🔍 Latest deploy log https://app.netlify.com/projects/holmes-docs/deploys/6a5f30ee9ea7260008284838
😎 Deploy Preview https://deploy-preview-2310--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.

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: cd262067-fd17-48c4-ac9f-5166b1193fe1

📥 Commits

Reviewing files that changed from the base of the PR and between 205e008 and fb2a664.

📒 Files selected for processing (3)
  • tests/llm/fixtures/test_ask_holmes/283_cpu_throttling_code_bug/deployment.yaml
  • tests/llm/fixtures/test_ask_holmes/283_cpu_throttling_code_bug/rate-sync.sh
  • tests/llm/fixtures/test_ask_holmes/283_cpu_throttling_code_bug/test_case.yaml
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/llm/fixtures/test_ask_holmes/283_cpu_throttling_code_bug/test_case.yaml
  • tests/llm/fixtures/test_ask_holmes/283_cpu_throttling_code_bug/deployment.yaml

Walkthrough

Adds sandbox limitation workarounds and a Kubernetes eval fixture containing a quote service, tariff cache, request worker, Loki logging, GitLab MCP access, Prometheus checks, and cleanup orchestration.

Changes

Sandbox guidance

Layer / File(s) Summary
Sandbox limitation workarounds
CLAUDE.md
Documents jq download, CPU CFS metrics, and pod TLS limitations with executable, exporter, and certificate workarounds.

CPU throttling eval

Layer / File(s) Summary
Quote service runtime
tests/llm/fixtures/test_ask_holmes/283_cpu_throttling_code_bug/app/*
Adds tariff matrix generation and caching, HTTP quote and health endpoints, structured logging, and service documentation.
Kubernetes workload wiring
tests/llm/fixtures/test_ask_holmes/283_cpu_throttling_code_bug/deployment.yaml, tests/llm/fixtures/test_ask_holmes/283_cpu_throttling_code_bug/rate-sync.sh
Deploys the quote service, request-generating worker, Promtail logging, and GitLab MCP services.
GitLab MCP source access
tests/llm/fixtures/test_ask_holmes/283_cpu_throttling_code_bug/gitlab_mcp_server.py
Exposes project metadata, repository files, commit history, and asynchronous repository tools.
Eval orchestration and tool configuration
tests/llm/fixtures/test_ask_holmes/283_cpu_throttling_code_bug/test_case.yaml, tests/llm/fixtures/test_ask_holmes/283_cpu_throttling_code_bug/toolsets.yaml
Configures observability tools and validates deployment readiness, Loki warnings, source contents, and CPU throttling before cleanup.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant RateSyncWorker
  participant QuoteService
  participant TariffEngine
  participant Loki
  RateSyncWorker->>QuoteService: Request quote
  QuoteService->>TariffEngine: Compute or retrieve matrix
  TariffEngine-->>QuoteService: Return matrix
  QuoteService->>TariffEngine: Select cheapest quote
  TariffEngine-->>QuoteService: Return quote
  QuoteService->>Loki: Write JSON timing log
  QuoteService-->>RateSyncWorker: Return quote response
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: adding eval 283 for a CPU throttling cache-key mismatch bug.
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.

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.

@github-actions

github-actions Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

✅ Results of HolmesGPT evals

Automatically triggered by commit 205e008 on branch claude/cpu-throttling-bug-eval-m2dev7 (labels: evals-id-283)

View workflow logs

Results of HolmesGPT evals

  • ask_holmes: 1/1 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 Skill Generated Skills Read Compactions Denied commands Src
✅ ✍️ 283_cpu_throttling_code_bug 111.8s 10 21 $0.6810 383,039 377,921 49,450 5,118 980 324,507 53,414 1,047 1 src
Total 111.8s avg 10.0 avg 21.0 avg $0.6810 383,039 377,921 49,450 5,118 980 324,507 53,414 1,047 1
Skills mechanism stats
  • Evals that emitted at least one memory: 1
  • Replays attempted: 0
  • Replays where the agent loaded the captured skill: 0/0
  • Replays that answered correctly: 0/0
  • Mean replay vs primary delta (per-row average): — cost, — tokens (n=0)
Benchmark Comparison Details

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

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

No baseline data available for comparison.

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/cpu-throttling-bug-eval-m2dev7 -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, fable-not-opus, fast, frontend, grafana, hard, images, integration, kafka, kubernetes, leaked-information, logs, loki, manual, mcp, medium, metrics, multi-cluster, 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, fable-5, 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, gpt-5.5, haiku-4.5, kimi-2.5, kimi-2.5-openrouter, opus-4.5, opus-4.6, opus-4.7, opus-4.8, 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/cpu-throttling-bug-eval-m2dev7 -f markers=regression -f filter=

@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: 3

🤖 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 `@CLAUDE.md`:
- Around line 640-643: Update the `/tmp/jq` executable shim described in the
workaround so its `sed` transformation removes the entire `"oomScoreAdj"`
property, including its value and surrounding JSON syntax, regardless of whether
the value is positive, negative, or formatted differently. Preserve the existing
emulation of the runc wrapper’s jq invocation.

In
`@tests/llm/fixtures/test_ask_holmes/283_cpu_throttling_code_bug/deployment.yaml`:
- Around line 149-168: Move the inline rate-sync shell script from the
Deployment container args into a neighboring rate-sync.sh file, and reference
that script through a Secret volume and mount. Update before_test to create the
Secret from rate-sync.sh, following the existing quote-service-src and
gitlab-mcp-code Secret patterns while preserving the worker command and
resource-efficient behavior.

In
`@tests/llm/fixtures/test_ask_holmes/283_cpu_throttling_code_bug/test_case.yaml`:
- Around line 153-156: Update Needle 2’s grep check in the deployment validation
to match the specific un-spaced cache write-key format, such as the
`f"{origin.upper()}->{dest.upper()}"` expression, instead of the broad `->`
pattern. Keep the existing failure handling and success message unchanged so the
check only passes when the buggy write-key line is present.
🪄 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: 0bc5e12f-a583-4a8c-9abf-0759a401a2d3

📥 Commits

Reviewing files that changed from the base of the PR and between 20fad32 and 205e008.

📒 Files selected for processing (8)
  • CLAUDE.md
  • tests/llm/fixtures/test_ask_holmes/283_cpu_throttling_code_bug/app/README.md
  • tests/llm/fixtures/test_ask_holmes/283_cpu_throttling_code_bug/app/server.py
  • tests/llm/fixtures/test_ask_holmes/283_cpu_throttling_code_bug/app/tariff_engine.py
  • tests/llm/fixtures/test_ask_holmes/283_cpu_throttling_code_bug/deployment.yaml
  • tests/llm/fixtures/test_ask_holmes/283_cpu_throttling_code_bug/gitlab_mcp_server.py
  • tests/llm/fixtures/test_ask_holmes/283_cpu_throttling_code_bug/test_case.yaml
  • tests/llm/fixtures/test_ask_holmes/283_cpu_throttling_code_bug/toolsets.yaml

Comment thread CLAUDE.md
Comment thread tests/llm/fixtures/test_ask_holmes/283_cpu_throttling_code_bug/deployment.yaml Outdated
- Tighten the needle-2 setup check: grep for the exact buggy write-key
  expression ('}->{dest.upper()}') instead of a bare '->', which also
  matched ordinary return-type annotations and could never fail.
- Move the rate-sync-worker loop out of inline Deployment args into
  rate-sync.sh, mounted from a Secret, matching the repo convention and
  the other scripts in this fixture.
- Drop the no-cicd tag: the labeled CI run executed this eval on the
  KIND cluster and it passed 1/1 (opus-4.6), proving the prerequisites
  (kube-prometheus, real CFS throttling, in-pod pip) all exist in CI.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016LXH3dCxNQNVHbHQTqjBgj
Signed-off-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants