Skip to content

skill-creator: fix parallel worker false negatives in run_eval.py - #794

Open
rhys-childs wants to merge 1 commit into
anthropics:mainfrom
rhys-childs:fix/run-eval-parallel-false-negatives
Open

skill-creator: fix parallel worker false negatives in run_eval.py#794
rhys-childs wants to merge 1 commit into
anthropics:mainfrom
rhys-childs:fix/run-eval-parallel-false-negatives

Conversation

@rhys-childs

@rhys-childs rhys-childs commented Mar 27, 2026

Copy link
Copy Markdown

run_eval.py creates a separate command file per parallel worker, each with a unique UUID. Claude picks one arbitrarily, but each worker only checks for its own UUID — so N-1 out of N workers report false negatives. At the default --num-workers 10, this produces the 0% trigger rate reported in #556.

The fix creates a single shared command file before spawning workers. All workers match against the same name. Full parallelism is preserved.


Reproduction

30-query eval set (15 should-trigger, 15 should-not), --runs-per-query 3, --num-workers 10 (default):

Before (per-worker files) After (shared file)
Should-trigger queries passed 0/15 15/15
Individual trigger runs 5/45 (11%) 45/45 (100%)

Concurrent eval runs for different skills were also tested — no cross-contamination.

What changes
Aspect Before After
Command files per eval run N (one per worker) 1 (shared)
Detection target Per-worker UUID Shared UUID
File lifecycle run_single_query creates/deletes run_eval creates/deletes
run_single_query params skill_name, skill_description command_name

Related issues

Fixes #556

Each parallel worker created its own command file with a unique UUID
suffix, then checked whether Claude invoked that specific UUID. When
multiple identically-described command files coexisted on disk, Claude
would pick one arbitrarily — but only the worker whose UUID was chosen
reported a trigger. All other concurrent workers reported false
negatives, producing artificially low trigger rates that scale
inversely with --num-workers (e.g. ~33% at 3 workers, ~0% at 10).

Fix: create a single shared command file in run_eval() before spawning
workers, so every claude -p session sees exactly one command and all
workers match against the same name. File cleanup moves to a finally
block in run_eval() that runs after ProcessPoolExecutor.shutdown()
guarantees all workers have completed.

Related to anthropics#556
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.

run_eval.py: claude -p never triggers skills/commands (0% trigger rate across all queries)

1 participant