General
condition-based-waiting - Claude MCP Skill
Use when tests have race conditions, timing dependencies, or inconsistent pass/fail behavior - replaces arbitrary timeouts with condition polling to wait for actual state changes, eliminating flaky tests from timing guesses
SEO Guide: Enhance your AI agent with the condition-based-waiting tool. This Model Context Protocol (MCP) server allows Claude Desktop and other LLMs to use when tests have race conditions, timing dependencies, or inconsistent pass/fail behavior - repla... Download and configure this skill to unlock new capabilities for your AI workflow.
Documentation
SKILL.md# Condition-Based Waiting
## Overview
Flaky tests often guess at timing with arbitrary delays. This creates race conditions where tests pass on fast machines but fail under load or in CI.
**Core principle:** Wait for the actual condition you care about, not a guess about how long it takes.
## When to Use
```dot
digraph when_to_use {
"Test uses setTimeout/sleep?" [shape=diamond];
"Testing timing behavior?" [shape=diamond];
"Document WHY timeout needed" [shape=box];
"Use condition-based waiting" [shape=box];
"Test uses setTimeout/sleep?" -> "Testing timing behavior?" [label="yes"];
"Testing timing behavior?" -> "Document WHY timeout needed" [label="yes"];
"Testing timing behavior?" -> "Use condition-based waiting" [label="no"];
}
```
**Use when:**
- Tests have arbitrary delays (`setTimeout`, `sleep`, `time.sleep()`)
- Tests are flaky (pass sometimes, fail under load)
- Tests timeout when run in parallel
- Waiting for async operations to complete
**Don't use when:**
- Testing actual timing behavior (debounce, throttle intervals)
- Always document WHY if using arbitrary timeout
## Core Pattern
```csharp
// ❌ BEFORE: Guessing at timing
await Task.Delay(50);
var result = GetResult();
Assert.NotNull(result);
// ✅ AFTER: Waiting for condition
await WaitForAsync(() => GetResult() != null);
var result = GetResult();
Assert.NotNull(result);
```
## Quick Patterns
| Scenario | Pattern |
|----------|---------|
| Wait for event | `await WaitForAsync(() => events.Any(e => e.Type == EventType.Done))` |
| Wait for state | `await WaitForAsync(() => machine.State == MachineState.Ready)` |
| Wait for count | `await WaitForAsync(() => items.Count >= 5)` |
| Wait for file | `await WaitForAsync(() => File.Exists(path))` |
| Complex condition | `await WaitForAsync(() => obj.IsReady && obj.Value > 10)` |
## Implementation
Generic polling function:
```csharp
public static async Task<T> WaitForAsync<T>(
Func<T?> condition,
string description,
int timeoutMs = 5000,
int pollIntervalMs = 10,
CancellationToken cancellationToken = default)
where T : class
{
var startTime = DateTime.UtcNow;
while (!cancellationToken.IsCancellationRequested)
{
var result = condition();
if (result != null) return result;
if ((DateTime.UtcNow - startTime).TotalMilliseconds > timeoutMs)
{
throw new TimeoutException($"Timeout waiting for {description} after {timeoutMs}ms");
}
await Task.Delay(pollIntervalMs, cancellationToken);
}
throw new OperationCanceledException();
}
// Overload for boolean conditions
public static async Task WaitForAsync(
Func<bool> condition,
string description,
int timeoutMs = 5000,
int pollIntervalMs = 10,
CancellationToken cancellationToken = default)
{
await WaitForAsync(() => condition() ? true : null, description, timeoutMs, pollIntervalMs, cancellationToken);
}
```
See @example.cs for complete implementation with domain-specific helpers (`WaitForEventAsync`, `WaitForEventCountAsync`, `WaitForEventMatchAsync`) from actual debugging session.
## Common Mistakes
**❌ Polling too fast:** `Task.Delay(1)` - wastes CPU
**✅ Fix:** Poll every 10ms
**❌ No timeout:** Loop forever if condition never met
**✅ Fix:** Always include timeout with clear error
**❌ Stale data:** Cache state before loop
**✅ Fix:** Call getter inside loop for fresh data
## When Arbitrary Timeout IS Correct
```csharp
// Tool ticks every 100ms - need 2 ticks to verify partial output
await WaitForEventAsync(manager, ToolEventType.Started); // First: wait for condition
await Task.Delay(200); // Then: wait for timed behavior
// 200ms = 2 ticks at 100ms intervals - documented and justified
```
**Requirements:**
1. First wait for triggering condition
2. Based on known timing (not guessing)
3. Comment explaining WHY
## Real-World Impact
From debugging session (2025-10-03):
- Fixed 15 flaky tests across 3 files
- Pass rate: 60% → 100%
- Execution time: 40% faster
- No more race conditionsSignals
Information
- Repository
- alexsandrocruz/ZenPowers
- Author
- alexsandrocruz
- Last Sync
- 3/13/2026
- Repo Updated
- 1/17/2026
- Created
- 1/12/2026
Reviews (0)
No reviews yet. Be the first to review this skill!
Related Skills
upgrade-nodejs
Upgrading Bun's Self-Reported Node.js Version
cursorrules
CrewAI Development Rules
Confidence Check
Pre-implementation confidence assessment (≥90% required). Use before starting any implementation to verify readiness with duplicate check, architecture compliance, official docs verification, OSS references, and root cause identification.
ollama_agent_guide
Ollama Agent Usage Guide
Related Guides
Python Django Best Practices: A Comprehensive Guide to the Claude Skill
Learn how to use the python django best practices Claude skill. Complete guide with installation instructions and examples.
Mastering Python Development with Claude: A Complete Guide to the Python Skill
Learn how to use the python Claude skill. Complete guide with installation instructions and examples.
Mastering VSCode Extension Development with Claude: A Complete Guide to the TypeScript Extension Dev Skill
Learn how to use the vscode extension dev typescript Claude skill. Complete guide with installation instructions and examples.