[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M77K5CFVCVV6GDZBJ25F53R5":3,"skill-same:01M77K5CFVCVV6GDZBJ25F53R5":80},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":16,"sourceHtmlUrl":17,"categories":18,"keywords":19,"publishedAt":20,"linkOnly":21,"markdownContent":22,"markdownBody":23,"frontMatter":24,"refName":25,"commitSha":26,"skillDirectory":27,"forksCount":14,"repositoryHtmlUrl":28,"repositoryHomepageUrl":6,"ownerHtmlUrl":29,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":30,"install":31,"resources":44},"01M77K5CFVCVV6GDZBJ25F53R5","condition-based-waiting",null,"Use when tests have race conditions, timing dependencies, or inconsistent pass\u002Ffail behavior - replaces arbitrary timeouts with condition polling to wait for actual state changes, eliminating flaky tests from timing guesses","jimbou\u002Fskillrace","jimbou","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F75038393?v=4","01M77K3V3GXQ0ZPCK28XKBMFXZ","Dimitrios Stamatios Bouras","01M77K3V49X9CT44G1T1KN621T",0,"MIT","https:\u002F\u002Fgithub.com\u002Fjimbou\u002Fskillrace\u002Fblob\u002Fmain\u002Fskills\u002Fcondition-based-waiting\u002FLICENSE.upstream","https:\u002F\u002Fgithub.com\u002Fjimbou\u002Fskillrace\u002Fblob\u002Fmain\u002Fskills\u002Fcondition-based-waiting\u002FSKILL.md",[],[],"2026-11-15 14:19:17",false,"---\nname: condition-based-waiting\ndescription: Use when tests have race conditions, timing dependencies, or inconsistent pass\u002Ffail behavior - replaces arbitrary timeouts with condition polling to wait for actual state changes, eliminating flaky tests from timing guesses\n---\n\n# Condition-Based Waiting\n\n## Overview\n\nFlaky 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.\n\n**Core principle:** Wait for the actual condition you care about, not a guess about how long it takes.\n\n## When to Use\n\n```dot\ndigraph when_to_use {\n    \"Test uses setTimeout\u002Fsleep?\" [shape=diamond];\n    \"Testing timing behavior?\" [shape=diamond];\n    \"Document WHY timeout needed\" [shape=box];\n    \"Use condition-based waiting\" [shape=box];\n\n    \"Test uses setTimeout\u002Fsleep?\" -> \"Testing timing behavior?\" [label=\"yes\"];\n    \"Testing timing behavior?\" -> \"Document WHY timeout needed\" [label=\"yes\"];\n    \"Testing timing behavior?\" -> \"Use condition-based waiting\" [label=\"no\"];\n}\n```\n\n**Use when:**\n- Tests have arbitrary delays (`setTimeout`, `sleep`, `time.sleep()`)\n- Tests are flaky (pass sometimes, fail under load)\n- Tests timeout when run in parallel\n- Waiting for async operations to complete\n\n**Don't use when:**\n- Testing actual timing behavior (debounce, throttle intervals)\n- Always document WHY if using arbitrary timeout\n\n## Core Pattern\n\n```typescript\n\u002F\u002F ❌ BEFORE: Guessing at timing\nawait new Promise(r => setTimeout(r, 50));\nconst result = getResult();\nexpect(result).toBeDefined();\n\n\u002F\u002F ✅ AFTER: Waiting for condition\nawait waitFor(() => getResult() !== undefined);\nconst result = getResult();\nexpect(result).toBeDefined();\n```\n\n## Quick Patterns\n\n| Scenario | Pattern |\n|----------|---------|\n| Wait for event | `waitFor(() => events.find(e => e.type === 'DONE'))` |\n| Wait for state | `waitFor(() => machine.state === 'ready')` |\n| Wait for count | `waitFor(() => items.length >= 5)` |\n| Wait for file | `waitFor(() => fs.existsSync(path))` |\n| Complex condition | `waitFor(() => obj.ready && obj.value > 10)` |\n\n## Implementation\n\nGeneric polling function:\n```typescript\nasync function waitFor\u003CT>(\n  condition: () => T | undefined | null | false,\n  description: string,\n  timeoutMs = 5000\n): Promise\u003CT> {\n  const startTime = Date.now();\n\n  while (true) {\n    const result = condition();\n    if (result) return result;\n\n    if (Date.now() - startTime > timeoutMs) {\n      throw new Error(`Timeout waiting for ${description} after ${timeoutMs}ms`);\n    }\n\n    await new Promise(r => setTimeout(r, 10)); \u002F\u002F Poll every 10ms\n  }\n}\n```\n\nSee @example.ts for complete implementation with domain-specific helpers (`waitForEvent`, `waitForEventCount`, `waitForEventMatch`) from actual debugging session.\n\n## Common Mistakes\n\n**❌ Polling too fast:** `setTimeout(check, 1)` - wastes CPU\n**✅ Fix:** Poll every 10ms\n\n**❌ No timeout:** Loop forever if condition never met\n**✅ Fix:** Always include timeout with clear error\n\n**❌ Stale data:** Cache state before loop\n**✅ Fix:** Call getter inside loop for fresh data\n\n## When Arbitrary Timeout IS Correct\n\n```typescript\n\u002F\u002F Tool ticks every 100ms - need 2 ticks to verify partial output\nawait waitForEvent(manager, 'TOOL_STARTED'); \u002F\u002F First: wait for condition\nawait new Promise(r => setTimeout(r, 200));   \u002F\u002F Then: wait for timed behavior\n\u002F\u002F 200ms = 2 ticks at 100ms intervals - documented and justified\n```\n\n**Requirements:**\n1. First wait for triggering condition\n2. Based on known timing (not guessing)\n3. Comment explaining WHY\n\n## Real-World Impact\n\nFrom debugging session (2025-10-03):\n- Fixed 15 flaky tests across 3 files\n- Pass rate: 60% → 100%\n- Execution time: 40% faster\n- No more race conditions\n","# Condition-Based Waiting\n\n## Overview\n\nFlaky 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.\n\n**Core principle:** Wait for the actual condition you care about, not a guess about how long it takes.\n\n## When to Use\n\n```dot\ndigraph when_to_use {\n    \"Test uses setTimeout\u002Fsleep?\" [shape=diamond];\n    \"Testing timing behavior?\" [shape=diamond];\n    \"Document WHY timeout needed\" [shape=box];\n    \"Use condition-based waiting\" [shape=box];\n\n    \"Test uses setTimeout\u002Fsleep?\" -> \"Testing timing behavior?\" [label=\"yes\"];\n    \"Testing timing behavior?\" -> \"Document WHY timeout needed\" [label=\"yes\"];\n    \"Testing timing behavior?\" -> \"Use condition-based waiting\" [label=\"no\"];\n}\n```\n\n**Use when:**\n- Tests have arbitrary delays (`setTimeout`, `sleep`, `time.sleep()`)\n- Tests are flaky (pass sometimes, fail under load)\n- Tests timeout when run in parallel\n- Waiting for async operations to complete\n\n**Don't use when:**\n- Testing actual timing behavior (debounce, throttle intervals)\n- Always document WHY if using arbitrary timeout\n\n## Core Pattern\n\n```typescript\n\u002F\u002F ❌ BEFORE: Guessing at timing\nawait new Promise(r => setTimeout(r, 50));\nconst result = getResult();\nexpect(result).toBeDefined();\n\n\u002F\u002F ✅ AFTER: Waiting for condition\nawait waitFor(() => getResult() !== undefined);\nconst result = getResult();\nexpect(result).toBeDefined();\n```\n\n## Quick Patterns\n\n| Scenario | Pattern |\n|----------|---------|\n| Wait for event | `waitFor(() => events.find(e => e.type === 'DONE'))` |\n| Wait for state | `waitFor(() => machine.state === 'ready')` |\n| Wait for count | `waitFor(() => items.length >= 5)` |\n| Wait for file | `waitFor(() => fs.existsSync(path))` |\n| Complex condition | `waitFor(() => obj.ready && obj.value > 10)` |\n\n## Implementation\n\nGeneric polling function:\n```typescript\nasync function waitFor\u003CT>(\n  condition: () => T | undefined | null | false,\n  description: string,\n  timeoutMs = 5000\n): Promise\u003CT> {\n  const startTime = Date.now();\n\n  while (true) {\n    const result = condition();\n    if (result) return result;\n\n    if (Date.now() - startTime > timeoutMs) {\n      throw new Error(`Timeout waiting for ${description} after ${timeoutMs}ms`);\n    }\n\n    await new Promise(r => setTimeout(r, 10)); \u002F\u002F Poll every 10ms\n  }\n}\n```\n\nSee @example.ts for complete implementation with domain-specific helpers (`waitForEvent`, `waitForEventCount`, `waitForEventMatch`) from actual debugging session.\n\n## Common Mistakes\n\n**❌ Polling too fast:** `setTimeout(check, 1)` - wastes CPU\n**✅ Fix:** Poll every 10ms\n\n**❌ No timeout:** Loop forever if condition never met\n**✅ Fix:** Always include timeout with clear error\n\n**❌ Stale data:** Cache state before loop\n**✅ Fix:** Call getter inside loop for fresh data\n\n## When Arbitrary Timeout IS Correct\n\n```typescript\n\u002F\u002F Tool ticks every 100ms - need 2 ticks to verify partial output\nawait waitForEvent(manager, 'TOOL_STARTED'); \u002F\u002F First: wait for condition\nawait new Promise(r => setTimeout(r, 200));   \u002F\u002F Then: wait for timed behavior\n\u002F\u002F 200ms = 2 ticks at 100ms intervals - documented and justified\n```\n\n**Requirements:**\n1. First wait for triggering condition\n2. Based on known timing (not guessing)\n3. Comment explaining WHY\n\n## Real-World Impact\n\nFrom debugging session (2025-10-03):\n- Fixed 15 flaky tests across 3 files\n- Pass rate: 60% → 100%\n- Execution time: 40% faster\n- No more race conditions\n",{"name":5,"description":7},"main","563b999846bcd88b8373821bd979061a6920cd76","skills\u002Fcondition-based-waiting","https:\u002F\u002Fgithub.com\u002Fjimbou\u002Fskillrace","https:\u002F\u002Fgithub.com\u002Fjimbou","2026-07-23 17:50:09",{"source":8,"skillName":5,"commands":32,"prompt":42,"zipAvailable":43},[33,36,39],{"tool":34,"command":35},"npx","npx skills add jimbou\u002Fskillrace --skill condition-based-waiting",{"tool":37,"command":38},"bunx","bunx skills add jimbou\u002Fskillrace --skill condition-based-waiting",{"tool":40,"command":41},"pnpm","pnpm dlx skills add jimbou\u002Fskillrace --skill condition-based-waiting","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fjimbou\u002Fskillrace\u002Fblob\u002Fmain\u002Fskills\u002Fcondition-based-waiting\u002FSKILL.md",true,[45,51,57,63,68,72,76],{"path":46,"resourceType":47,"resourceTypeDesc":48,"sizeBytes":49,"sourceHtmlUrl":50},"applicability.json","REFERENCE","参考文档",488,"https:\u002F\u002Fgithub.com\u002Fjimbou\u002Fskillrace\u002Fblob\u002Fmain\u002Fskills\u002Fcondition-based-waiting\u002Fapplicability.json",{"path":52,"resourceType":53,"resourceTypeDesc":54,"sizeBytes":55,"sourceHtmlUrl":56},"Containerfile.base","OTHER","其他",315,"https:\u002F\u002Fgithub.com\u002Fjimbou\u002Fskillrace\u002Fblob\u002Fmain\u002Fskills\u002Fcondition-based-waiting\u002FContainerfile.base",{"path":58,"resourceType":59,"resourceTypeDesc":60,"sizeBytes":61,"sourceHtmlUrl":62},"example.ts","SCRIPT","脚本",5054,"https:\u002F\u002Fgithub.com\u002Fjimbou\u002Fskillrace\u002Fblob\u002Fmain\u002Fskills\u002Fcondition-based-waiting\u002Fexample.ts",{"path":64,"resourceType":65,"resourceTypeDesc":66,"sizeBytes":67,"sourceHtmlUrl":16},"LICENSE.upstream","LICENSE","许可证",1070,{"path":69,"resourceType":47,"resourceTypeDesc":48,"sizeBytes":70,"sourceHtmlUrl":71},"properties.json",1421,"https:\u002F\u002Fgithub.com\u002Fjimbou\u002Fskillrace\u002Fblob\u002Fmain\u002Fskills\u002Fcondition-based-waiting\u002Fproperties.json",{"path":73,"resourceType":47,"resourceTypeDesc":48,"sizeBytes":74,"sourceHtmlUrl":75},"PROVENANCE.md",1100,"https:\u002F\u002Fgithub.com\u002Fjimbou\u002Fskillrace\u002Fblob\u002Fmain\u002Fskills\u002Fcondition-based-waiting\u002FPROVENANCE.md",{"path":77,"resourceType":47,"resourceTypeDesc":48,"sizeBytes":78,"sourceHtmlUrl":79},"repo\u002FREADME.md",114,"https:\u002F\u002Fgithub.com\u002Fjimbou\u002Fskillrace\u002Fblob\u002Fmain\u002Fskills\u002Fcondition-based-waiting\u002Frepo\u002FREADME.md",[81],{"skillNo":82,"name":83,"nameZh":6,"description":84,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":85,"licenseFileUrl":6,"sourceHtmlUrl":86,"categories":87,"keywords":88,"publishedAt":20},"01M77K7JQECPNZTHRYCZ6TB7SB","unit-test-generator","Automatically generate unit tests based on source code, supporting multiple languages and testing frameworks.","CC0-1.0","https:\u002F\u002Fgithub.com\u002Fjimbou\u002Fskillrace\u002Fblob\u002Fmain\u002Fskills\u002Funit-test-generator\u002FSKILL.md",[],[]]