[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-openai-test-driven-development":3,"mdc-4exvfb-key":33,"related-repo-openai-test-driven-development":2057,"related-org-openai-test-driven-development":2179},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":11,"stars":22,"repoUrl":23,"updatedAt":24,"license":25,"forks":26,"topics":27,"repo":28,"sourceUrl":31,"mdContent":32},"test-driven-development","implement features with test-driven development","Use when implementing any feature or bugfix, before writing implementation code",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},"openai","OpenAI","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Fopenai.png",[12,16,19],{"name":13,"slug":14,"type":15},"QA","qa","tag",{"name":17,"slug":18,"type":15},"Engineering","engineering",{"name":20,"slug":21,"type":15},"Testing","testing",3992,"https:\u002F\u002Fgithub.com\u002Fopenai\u002Fplugins","2026-04-16T05:11:56.347812",null,465,[],{"repoUrl":23,"stars":22,"forks":26,"topics":29,"description":30},[],"OpenAI Plugins","https:\u002F\u002Fgithub.com\u002Fopenai\u002Fplugins\u002Ftree\u002FHEAD\u002Fplugins\u002Fsuperpowers\u002Fskills\u002Ftest-driven-development","---\nname: test-driven-development\ndescription: Use when implementing any feature or bugfix, before writing implementation code\n---\n\n# Test-Driven Development (TDD)\n\n## Overview\n\nWrite the test first. Watch it fail. Write minimal code to pass.\n\n**Core principle:** If you didn't watch the test fail, you don't know if it tests the right thing.\n\n**Violating the letter of the rules is violating the spirit of the rules.**\n\n## When to Use\n\n**Always:**\n- New features\n- Bug fixes\n- Refactoring\n- Behavior changes\n\n**Exceptions (ask your human partner):**\n- Throwaway prototypes\n- Generated code\n- Configuration files\n\nThinking \"skip TDD just this once\"? Stop. That's rationalization.\n\n## The Iron Law\n\n```\nNO PRODUCTION CODE WITHOUT A FAILING TEST FIRST\n```\n\nWrite code before the test? Delete it. Start over.\n\n**No exceptions:**\n- Don't keep it as \"reference\"\n- Don't \"adapt\" it while writing tests\n- Don't look at it\n- Delete means delete\n\nImplement fresh from tests. Period.\n\n## Red-Green-Refactor\n\n```dot\ndigraph tdd_cycle {\n    rankdir=LR;\n    red [label=\"RED\\nWrite failing test\", shape=box, style=filled, fillcolor=\"#ffcccc\"];\n    verify_red [label=\"Verify fails\\ncorrectly\", shape=diamond];\n    green [label=\"GREEN\\nMinimal code\", shape=box, style=filled, fillcolor=\"#ccffcc\"];\n    verify_green [label=\"Verify passes\\nAll green\", shape=diamond];\n    refactor [label=\"REFACTOR\\nClean up\", shape=box, style=filled, fillcolor=\"#ccccff\"];\n    next [label=\"Next\", shape=ellipse];\n\n    red -> verify_red;\n    verify_red -> green [label=\"yes\"];\n    verify_red -> red [label=\"wrong\\nfailure\"];\n    green -> verify_green;\n    verify_green -> refactor [label=\"yes\"];\n    verify_green -> green [label=\"no\"];\n    refactor -> verify_green [label=\"stay\\ngreen\"];\n    verify_green -> next;\n    next -> red;\n}\n```\n\n### RED - Write Failing Test\n\nWrite one minimal test showing what should happen.\n\n\u003CGood>\n```typescript\ntest('retries failed operations 3 times', async () => {\n  let attempts = 0;\n  const operation = () => {\n    attempts++;\n    if (attempts \u003C 3) throw new Error('fail');\n    return 'success';\n  };\n\n  const result = await retryOperation(operation);\n\n  expect(result).toBe('success');\n  expect(attempts).toBe(3);\n});\n```\nClear name, tests real behavior, one thing\n\u003C\u002FGood>\n\n\u003CBad>\n```typescript\ntest('retry works', async () => {\n  const mock = jest.fn()\n    .mockRejectedValueOnce(new Error())\n    .mockRejectedValueOnce(new Error())\n    .mockResolvedValueOnce('success');\n  await retryOperation(mock);\n  expect(mock).toHaveBeenCalledTimes(3);\n});\n```\nVague name, tests mock not code\n\u003C\u002FBad>\n\n**Requirements:**\n- One behavior\n- Clear name\n- Real code (no mocks unless unavoidable)\n\n### Verify RED - Watch It Fail\n\n**MANDATORY. Never skip.**\n\n```bash\nnpm test path\u002Fto\u002Ftest.test.ts\n```\n\nConfirm:\n- Test fails (not errors)\n- Failure message is expected\n- Fails because feature missing (not typos)\n\n**Test passes?** You're testing existing behavior. Fix test.\n\n**Test errors?** Fix error, re-run until it fails correctly.\n\n### GREEN - Minimal Code\n\nWrite simplest code to pass the test.\n\n\u003CGood>\n```typescript\nasync function retryOperation\u003CT>(fn: () => Promise\u003CT>): Promise\u003CT> {\n  for (let i = 0; i \u003C 3; i++) {\n    try {\n      return await fn();\n    } catch (e) {\n      if (i === 2) throw e;\n    }\n  }\n  throw new Error('unreachable');\n}\n```\nJust enough to pass\n\u003C\u002FGood>\n\n\u003CBad>\n```typescript\nasync function retryOperation\u003CT>(\n  fn: () => Promise\u003CT>,\n  options?: {\n    maxRetries?: number;\n    backoff?: 'linear' | 'exponential';\n    onRetry?: (attempt: number) => void;\n  }\n): Promise\u003CT> {\n  \u002F\u002F YAGNI\n}\n```\nOver-engineered\n\u003C\u002FBad>\n\nDon't add features, refactor other code, or \"improve\" beyond the test.\n\n### Verify GREEN - Watch It Pass\n\n**MANDATORY.**\n\n```bash\nnpm test path\u002Fto\u002Ftest.test.ts\n```\n\nConfirm:\n- Test passes\n- Other tests still pass\n- Output pristine (no errors, warnings)\n\n**Test fails?** Fix code, not test.\n\n**Other tests fail?** Fix now.\n\n### REFACTOR - Clean Up\n\nAfter green only:\n- Remove duplication\n- Improve names\n- Extract helpers\n\nKeep tests green. Don't add behavior.\n\n### Repeat\n\nNext failing test for next feature.\n\n## Good Tests\n\n| Quality | Good | Bad |\n|---------|------|-----|\n| **Minimal** | One thing. \"and\" in name? Split it. | `test('validates email and domain and whitespace')` |\n| **Clear** | Name describes behavior | `test('test1')` |\n| **Shows intent** | Demonstrates desired API | Obscures what code should do |\n\n## Why Order Matters\n\n**\"I'll write tests after to verify it works\"**\n\nTests written after code pass immediately. Passing immediately proves nothing:\n- Might test wrong thing\n- Might test implementation, not behavior\n- Might miss edge cases you forgot\n- You never saw it catch the bug\n\nTest-first forces you to see the test fail, proving it actually tests something.\n\n**\"I already manually tested all the edge cases\"**\n\nManual testing is ad-hoc. You think you tested everything but:\n- No record of what you tested\n- Can't re-run when code changes\n- Easy to forget cases under pressure\n- \"It worked when I tried it\" ≠ comprehensive\n\nAutomated tests are systematic. They run the same way every time.\n\n**\"Deleting X hours of work is wasteful\"**\n\nSunk cost fallacy. The time is already gone. Your choice now:\n- Delete and rewrite with TDD (X more hours, high confidence)\n- Keep it and add tests after (30 min, low confidence, likely bugs)\n\nThe \"waste\" is keeping code you can't trust. Working code without real tests is technical debt.\n\n**\"TDD is dogmatic, being pragmatic means adapting\"**\n\nTDD IS pragmatic:\n- Finds bugs before commit (faster than debugging after)\n- Prevents regressions (tests catch breaks immediately)\n- Documents behavior (tests show how to use code)\n- Enables refactoring (change freely, tests catch breaks)\n\n\"Pragmatic\" shortcuts = debugging in production = slower.\n\n**\"Tests after achieve the same goals - it's spirit not ritual\"**\n\nNo. Tests-after answer \"What does this do?\" Tests-first answer \"What should this do?\"\n\nTests-after are biased by your implementation. You test what you built, not what's required. You verify remembered edge cases, not discovered ones.\n\nTests-first force edge case discovery before implementing. Tests-after verify you remembered everything (you didn't).\n\n30 minutes of tests after ≠ TDD. You get coverage, lose proof tests work.\n\n## Common Rationalizations\n\n| Excuse | Reality |\n|--------|---------|\n| \"Too simple to test\" | Simple code breaks. Test takes 30 seconds. |\n| \"I'll test after\" | Tests passing immediately prove nothing. |\n| \"Tests after achieve same goals\" | Tests-after = \"what does this do?\" Tests-first = \"what should this do?\" |\n| \"Already manually tested\" | Ad-hoc ≠ systematic. No record, can't re-run. |\n| \"Deleting X hours is wasteful\" | Sunk cost fallacy. Keeping unverified code is technical debt. |\n| \"Keep as reference, write tests first\" | You'll adapt it. That's testing after. Delete means delete. |\n| \"Need to explore first\" | Fine. Throw away exploration, start with TDD. |\n| \"Test hard = design unclear\" | Listen to test. Hard to test = hard to use. |\n| \"TDD will slow me down\" | TDD faster than debugging. Pragmatic = test-first. |\n| \"Manual test faster\" | Manual doesn't prove edge cases. You'll re-test every change. |\n| \"Existing code has no tests\" | You're improving it. Add tests for existing code. |\n\n## Red Flags - STOP and Start Over\n\n- Code before test\n- Test after implementation\n- Test passes immediately\n- Can't explain why test failed\n- Tests added \"later\"\n- Rationalizing \"just this once\"\n- \"I already manually tested it\"\n- \"Tests after achieve the same purpose\"\n- \"It's about spirit not ritual\"\n- \"Keep as reference\" or \"adapt existing code\"\n- \"Already spent X hours, deleting is wasteful\"\n- \"TDD is dogmatic, I'm being pragmatic\"\n- \"This is different because...\"\n\n**All of these mean: Delete code. Start over with TDD.**\n\n## Example: Bug Fix\n\n**Bug:** Empty email accepted\n\n**RED**\n```typescript\ntest('rejects empty email', async () => {\n  const result = await submitForm({ email: '' });\n  expect(result.error).toBe('Email required');\n});\n```\n\n**Verify RED**\n```bash\n$ npm test\nFAIL: expected 'Email required', got undefined\n```\n\n**GREEN**\n```typescript\nfunction submitForm(data: FormData) {\n  if (!data.email?.trim()) {\n    return { error: 'Email required' };\n  }\n  \u002F\u002F ...\n}\n```\n\n**Verify GREEN**\n```bash\n$ npm test\nPASS\n```\n\n**REFACTOR**\nExtract validation for multiple fields if needed.\n\n## Verification Checklist\n\nBefore marking work complete:\n\n- [ ] Every new function\u002Fmethod has a test\n- [ ] Watched each test fail before implementing\n- [ ] Each test failed for expected reason (feature missing, not typo)\n- [ ] Wrote minimal code to pass each test\n- [ ] All tests pass\n- [ ] Output pristine (no errors, warnings)\n- [ ] Tests use real code (mocks only if unavoidable)\n- [ ] Edge cases and errors covered\n\nCan't check all boxes? You skipped TDD. Start over.\n\n## When Stuck\n\n| Problem | Solution |\n|---------|----------|\n| Don't know how to test | Write wished-for API. Write assertion first. Ask your human partner. |\n| Test too complicated | Design too complicated. Simplify interface. |\n| Must mock everything | Code too coupled. Use dependency injection. |\n| Test setup huge | Extract helpers. Still complex? Simplify design. |\n\n## Debugging Integration\n\nBug found? Write failing test reproducing it. Follow TDD cycle. Test proves fix and prevents regression.\n\nNever fix bugs without a test.\n\n## Testing Anti-Patterns\n\nWhen adding mocks or test utilities, read @testing-anti-patterns.md to avoid common pitfalls:\n- Testing mock behavior instead of real behavior\n- Adding test-only methods to production classes\n- Mocking without understanding dependencies\n\n## Final Rule\n\n```\nProduction code → test exists and failed first\nOtherwise → not TDD\n```\n\nNo exceptions without your human partner's permission.\n",{"data":34,"body":35},{"name":4,"description":6},{"type":36,"children":37},"root",[38,47,54,60,71,79,85,93,118,126,144,149,155,168,173,181,204,209,215,398,405,410,2051],{"type":39,"tag":40,"props":41,"children":43},"element","h1",{"id":42},"test-driven-development-tdd",[44],{"type":45,"value":46},"text","Test-Driven Development (TDD)",{"type":39,"tag":48,"props":49,"children":51},"h2",{"id":50},"overview",[52],{"type":45,"value":53},"Overview",{"type":39,"tag":55,"props":56,"children":57},"p",{},[58],{"type":45,"value":59},"Write the test first. Watch it fail. Write minimal code to pass.",{"type":39,"tag":55,"props":61,"children":62},{},[63,69],{"type":39,"tag":64,"props":65,"children":66},"strong",{},[67],{"type":45,"value":68},"Core principle:",{"type":45,"value":70}," If you didn't watch the test fail, you don't know if it tests the right thing.",{"type":39,"tag":55,"props":72,"children":73},{},[74],{"type":39,"tag":64,"props":75,"children":76},{},[77],{"type":45,"value":78},"Violating the letter of the rules is violating the spirit of the rules.",{"type":39,"tag":48,"props":80,"children":82},{"id":81},"when-to-use",[83],{"type":45,"value":84},"When to Use",{"type":39,"tag":55,"props":86,"children":87},{},[88],{"type":39,"tag":64,"props":89,"children":90},{},[91],{"type":45,"value":92},"Always:",{"type":39,"tag":94,"props":95,"children":96},"ul",{},[97,103,108,113],{"type":39,"tag":98,"props":99,"children":100},"li",{},[101],{"type":45,"value":102},"New features",{"type":39,"tag":98,"props":104,"children":105},{},[106],{"type":45,"value":107},"Bug fixes",{"type":39,"tag":98,"props":109,"children":110},{},[111],{"type":45,"value":112},"Refactoring",{"type":39,"tag":98,"props":114,"children":115},{},[116],{"type":45,"value":117},"Behavior changes",{"type":39,"tag":55,"props":119,"children":120},{},[121],{"type":39,"tag":64,"props":122,"children":123},{},[124],{"type":45,"value":125},"Exceptions (ask your human partner):",{"type":39,"tag":94,"props":127,"children":128},{},[129,134,139],{"type":39,"tag":98,"props":130,"children":131},{},[132],{"type":45,"value":133},"Throwaway prototypes",{"type":39,"tag":98,"props":135,"children":136},{},[137],{"type":45,"value":138},"Generated code",{"type":39,"tag":98,"props":140,"children":141},{},[142],{"type":45,"value":143},"Configuration files",{"type":39,"tag":55,"props":145,"children":146},{},[147],{"type":45,"value":148},"Thinking \"skip TDD just this once\"? Stop. That's rationalization.",{"type":39,"tag":48,"props":150,"children":152},{"id":151},"the-iron-law",[153],{"type":45,"value":154},"The Iron Law",{"type":39,"tag":156,"props":157,"children":161},"pre",{"className":158,"code":160,"language":45},[159],"language-text","NO PRODUCTION CODE WITHOUT A FAILING TEST FIRST\n",[162],{"type":39,"tag":163,"props":164,"children":166},"code",{"__ignoreMap":165},"",[167],{"type":45,"value":160},{"type":39,"tag":55,"props":169,"children":170},{},[171],{"type":45,"value":172},"Write code before the test? Delete it. Start over.",{"type":39,"tag":55,"props":174,"children":175},{},[176],{"type":39,"tag":64,"props":177,"children":178},{},[179],{"type":45,"value":180},"No exceptions:",{"type":39,"tag":94,"props":182,"children":183},{},[184,189,194,199],{"type":39,"tag":98,"props":185,"children":186},{},[187],{"type":45,"value":188},"Don't keep it as \"reference\"",{"type":39,"tag":98,"props":190,"children":191},{},[192],{"type":45,"value":193},"Don't \"adapt\" it while writing tests",{"type":39,"tag":98,"props":195,"children":196},{},[197],{"type":45,"value":198},"Don't look at it",{"type":39,"tag":98,"props":200,"children":201},{},[202],{"type":45,"value":203},"Delete means delete",{"type":39,"tag":55,"props":205,"children":206},{},[207],{"type":45,"value":208},"Implement fresh from tests. Period.",{"type":39,"tag":48,"props":210,"children":212},{"id":211},"red-green-refactor",[213],{"type":45,"value":214},"Red-Green-Refactor",{"type":39,"tag":156,"props":216,"children":220},{"className":217,"code":218,"language":219,"meta":165,"style":165},"language-dot shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","digraph tdd_cycle {\n    rankdir=LR;\n    red [label=\"RED\\nWrite failing test\", shape=box, style=filled, fillcolor=\"#ffcccc\"];\n    verify_red [label=\"Verify fails\\ncorrectly\", shape=diamond];\n    green [label=\"GREEN\\nMinimal code\", shape=box, style=filled, fillcolor=\"#ccffcc\"];\n    verify_green [label=\"Verify passes\\nAll green\", shape=diamond];\n    refactor [label=\"REFACTOR\\nClean up\", shape=box, style=filled, fillcolor=\"#ccccff\"];\n    next [label=\"Next\", shape=ellipse];\n\n    red -> verify_red;\n    verify_red -> green [label=\"yes\"];\n    verify_red -> red [label=\"wrong\\nfailure\"];\n    green -> verify_green;\n    verify_green -> refactor [label=\"yes\"];\n    verify_green -> green [label=\"no\"];\n    refactor -> verify_green [label=\"stay\\ngreen\"];\n    verify_green -> next;\n    next -> red;\n}\n","dot",[221],{"type":39,"tag":163,"props":222,"children":223},{"__ignoreMap":165},[224,235,244,253,262,271,280,289,298,308,317,326,335,344,353,362,371,380,389],{"type":39,"tag":225,"props":226,"children":229},"span",{"class":227,"line":228},"line",1,[230],{"type":39,"tag":225,"props":231,"children":232},{},[233],{"type":45,"value":234},"digraph tdd_cycle {\n",{"type":39,"tag":225,"props":236,"children":238},{"class":227,"line":237},2,[239],{"type":39,"tag":225,"props":240,"children":241},{},[242],{"type":45,"value":243},"    rankdir=LR;\n",{"type":39,"tag":225,"props":245,"children":247},{"class":227,"line":246},3,[248],{"type":39,"tag":225,"props":249,"children":250},{},[251],{"type":45,"value":252},"    red [label=\"RED\\nWrite failing test\", shape=box, style=filled, fillcolor=\"#ffcccc\"];\n",{"type":39,"tag":225,"props":254,"children":256},{"class":227,"line":255},4,[257],{"type":39,"tag":225,"props":258,"children":259},{},[260],{"type":45,"value":261},"    verify_red [label=\"Verify fails\\ncorrectly\", shape=diamond];\n",{"type":39,"tag":225,"props":263,"children":265},{"class":227,"line":264},5,[266],{"type":39,"tag":225,"props":267,"children":268},{},[269],{"type":45,"value":270},"    green [label=\"GREEN\\nMinimal code\", shape=box, style=filled, fillcolor=\"#ccffcc\"];\n",{"type":39,"tag":225,"props":272,"children":274},{"class":227,"line":273},6,[275],{"type":39,"tag":225,"props":276,"children":277},{},[278],{"type":45,"value":279},"    verify_green [label=\"Verify passes\\nAll green\", shape=diamond];\n",{"type":39,"tag":225,"props":281,"children":283},{"class":227,"line":282},7,[284],{"type":39,"tag":225,"props":285,"children":286},{},[287],{"type":45,"value":288},"    refactor [label=\"REFACTOR\\nClean up\", shape=box, style=filled, fillcolor=\"#ccccff\"];\n",{"type":39,"tag":225,"props":290,"children":292},{"class":227,"line":291},8,[293],{"type":39,"tag":225,"props":294,"children":295},{},[296],{"type":45,"value":297},"    next [label=\"Next\", shape=ellipse];\n",{"type":39,"tag":225,"props":299,"children":301},{"class":227,"line":300},9,[302],{"type":39,"tag":225,"props":303,"children":305},{"emptyLinePlaceholder":304},true,[306],{"type":45,"value":307},"\n",{"type":39,"tag":225,"props":309,"children":311},{"class":227,"line":310},10,[312],{"type":39,"tag":225,"props":313,"children":314},{},[315],{"type":45,"value":316},"    red -> verify_red;\n",{"type":39,"tag":225,"props":318,"children":320},{"class":227,"line":319},11,[321],{"type":39,"tag":225,"props":322,"children":323},{},[324],{"type":45,"value":325},"    verify_red -> green [label=\"yes\"];\n",{"type":39,"tag":225,"props":327,"children":329},{"class":227,"line":328},12,[330],{"type":39,"tag":225,"props":331,"children":332},{},[333],{"type":45,"value":334},"    verify_red -> red [label=\"wrong\\nfailure\"];\n",{"type":39,"tag":225,"props":336,"children":338},{"class":227,"line":337},13,[339],{"type":39,"tag":225,"props":340,"children":341},{},[342],{"type":45,"value":343},"    green -> verify_green;\n",{"type":39,"tag":225,"props":345,"children":347},{"class":227,"line":346},14,[348],{"type":39,"tag":225,"props":349,"children":350},{},[351],{"type":45,"value":352},"    verify_green -> refactor [label=\"yes\"];\n",{"type":39,"tag":225,"props":354,"children":356},{"class":227,"line":355},15,[357],{"type":39,"tag":225,"props":358,"children":359},{},[360],{"type":45,"value":361},"    verify_green -> green [label=\"no\"];\n",{"type":39,"tag":225,"props":363,"children":365},{"class":227,"line":364},16,[366],{"type":39,"tag":225,"props":367,"children":368},{},[369],{"type":45,"value":370},"    refactor -> verify_green [label=\"stay\\ngreen\"];\n",{"type":39,"tag":225,"props":372,"children":374},{"class":227,"line":373},17,[375],{"type":39,"tag":225,"props":376,"children":377},{},[378],{"type":45,"value":379},"    verify_green -> next;\n",{"type":39,"tag":225,"props":381,"children":383},{"class":227,"line":382},18,[384],{"type":39,"tag":225,"props":385,"children":386},{},[387],{"type":45,"value":388},"    next -> red;\n",{"type":39,"tag":225,"props":390,"children":392},{"class":227,"line":391},19,[393],{"type":39,"tag":225,"props":394,"children":395},{},[396],{"type":45,"value":397},"}\n",{"type":39,"tag":399,"props":400,"children":402},"h3",{"id":401},"red-write-failing-test",[403],{"type":45,"value":404},"RED - Write Failing Test",{"type":39,"tag":55,"props":406,"children":407},{},[408],{"type":45,"value":409},"Write one minimal test showing what should happen.",{"type":39,"tag":411,"props":412,"children":413},"good",{},[414,416,421,426,435,440,448,466,472,480,509,514,532,542,552,558,563,584,604,609,615,623,644,648,666,676,686,692,697,715,720,726,731,737,841,847,855,860,883,888,896,901,924,929,937,942,955,960,968,973,996,1001,1009,1014,1019,1024,1029,1035,1200,1206,1274,1282,1288,1298,1306,1521,1529,1594,1602,1762,1770,1800,1810,1816,1821,1901,1906,1912,1986,1992,1997,2002,2008,2013,2031,2037,2046],{"type":45,"value":415},"\n```typescript\ntest('retries failed operations 3 times', async () => {\n  let attempts = 0;\n  const operation = () => {\n    attempts++;\n    if (attempts \u003C 3) throw new Error('fail');\n    return 'success';\n  };\n",{"type":39,"tag":55,"props":417,"children":418},{},[419],{"type":45,"value":420},"const result = await retryOperation(operation);",{"type":39,"tag":55,"props":422,"children":423},{},[424],{"type":45,"value":425},"expect(result).toBe('success');\nexpect(attempts).toBe(3);\n});",{"type":39,"tag":156,"props":427,"children":430},{"className":428,"code":429,"language":45},[159],"Clear name, tests real behavior, one thing\n\u003C\u002FGood>\n\n\u003CBad>\n```typescript\ntest('retry works', async () => {\n  const mock = jest.fn()\n    .mockRejectedValueOnce(new Error())\n    .mockRejectedValueOnce(new Error())\n    .mockResolvedValueOnce('success');\n  await retryOperation(mock);\n  expect(mock).toHaveBeenCalledTimes(3);\n});\n",[431],{"type":39,"tag":163,"props":432,"children":433},{"__ignoreMap":165},[434],{"type":45,"value":429},{"type":39,"tag":55,"props":436,"children":437},{},[438],{"type":45,"value":439},"Vague name, tests mock not code\n",{"type":39,"tag":55,"props":441,"children":442},{},[443],{"type":39,"tag":64,"props":444,"children":445},{},[446],{"type":45,"value":447},"Requirements:",{"type":39,"tag":94,"props":449,"children":450},{},[451,456,461],{"type":39,"tag":98,"props":452,"children":453},{},[454],{"type":45,"value":455},"One behavior",{"type":39,"tag":98,"props":457,"children":458},{},[459],{"type":45,"value":460},"Clear name",{"type":39,"tag":98,"props":462,"children":463},{},[464],{"type":45,"value":465},"Real code (no mocks unless unavoidable)",{"type":39,"tag":399,"props":467,"children":469},{"id":468},"verify-red-watch-it-fail",[470],{"type":45,"value":471},"Verify RED - Watch It Fail",{"type":39,"tag":55,"props":473,"children":474},{},[475],{"type":39,"tag":64,"props":476,"children":477},{},[478],{"type":45,"value":479},"MANDATORY. Never skip.",{"type":39,"tag":156,"props":481,"children":485},{"className":482,"code":483,"language":484,"meta":165,"style":165},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","npm test path\u002Fto\u002Ftest.test.ts\n","bash",[486],{"type":39,"tag":163,"props":487,"children":488},{"__ignoreMap":165},[489],{"type":39,"tag":225,"props":490,"children":491},{"class":227,"line":228},[492,498,504],{"type":39,"tag":225,"props":493,"children":495},{"style":494},"--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B",[496],{"type":45,"value":497},"npm",{"type":39,"tag":225,"props":499,"children":501},{"style":500},"--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D",[502],{"type":45,"value":503}," test",{"type":39,"tag":225,"props":505,"children":506},{"style":500},[507],{"type":45,"value":508}," path\u002Fto\u002Ftest.test.ts\n",{"type":39,"tag":55,"props":510,"children":511},{},[512],{"type":45,"value":513},"Confirm:",{"type":39,"tag":94,"props":515,"children":516},{},[517,522,527],{"type":39,"tag":98,"props":518,"children":519},{},[520],{"type":45,"value":521},"Test fails (not errors)",{"type":39,"tag":98,"props":523,"children":524},{},[525],{"type":45,"value":526},"Failure message is expected",{"type":39,"tag":98,"props":528,"children":529},{},[530],{"type":45,"value":531},"Fails because feature missing (not typos)",{"type":39,"tag":55,"props":533,"children":534},{},[535,540],{"type":39,"tag":64,"props":536,"children":537},{},[538],{"type":45,"value":539},"Test passes?",{"type":45,"value":541}," You're testing existing behavior. Fix test.",{"type":39,"tag":55,"props":543,"children":544},{},[545,550],{"type":39,"tag":64,"props":546,"children":547},{},[548],{"type":45,"value":549},"Test errors?",{"type":45,"value":551}," Fix error, re-run until it fails correctly.",{"type":39,"tag":399,"props":553,"children":555},{"id":554},"green-minimal-code",[556],{"type":45,"value":557},"GREEN - Minimal Code",{"type":39,"tag":55,"props":559,"children":560},{},[561],{"type":45,"value":562},"Write simplest code to pass the test.",{"type":39,"tag":411,"props":564,"children":565},{},[566,568],{"type":45,"value":567},"\n```typescript\nasync function retryOperation",{"type":39,"tag":569,"props":570,"children":571},"t",{},[572,574],{"type":45,"value":573},"(fn: () => Promise",{"type":39,"tag":569,"props":575,"children":576},{},[577,579],{"type":45,"value":578},"): Promise",{"type":39,"tag":569,"props":580,"children":581},{},[582],{"type":45,"value":583}," {\n  for (let i = 0; i \u003C 3; i++) {\n    try {\n      return await fn();\n    } catch (e) {\n      if (i === 2) throw e;\n    }\n  }\n  throw new Error('unreachable');\n}\n```\nJust enough to pass\n",{"type":39,"tag":585,"props":586,"children":587},"bad",{},[588,589],{"type":45,"value":567},{"type":39,"tag":569,"props":590,"children":591},{},[592,594],{"type":45,"value":593},"(\n  fn: () => Promise",{"type":39,"tag":569,"props":595,"children":596},{},[597,599],{"type":45,"value":598},",\n  options?: {\n    maxRetries?: number;\n    backoff?: 'linear' | 'exponential';\n    onRetry?: (attempt: number) => void;\n  }\n): Promise",{"type":39,"tag":569,"props":600,"children":601},{},[602],{"type":45,"value":603}," {\n  \u002F\u002F YAGNI\n}\n```\nOver-engineered\n",{"type":39,"tag":55,"props":605,"children":606},{},[607],{"type":45,"value":608},"Don't add features, refactor other code, or \"improve\" beyond the test.",{"type":39,"tag":399,"props":610,"children":612},{"id":611},"verify-green-watch-it-pass",[613],{"type":45,"value":614},"Verify GREEN - Watch It Pass",{"type":39,"tag":55,"props":616,"children":617},{},[618],{"type":39,"tag":64,"props":619,"children":620},{},[621],{"type":45,"value":622},"MANDATORY.",{"type":39,"tag":156,"props":624,"children":625},{"className":482,"code":483,"language":484,"meta":165,"style":165},[626],{"type":39,"tag":163,"props":627,"children":628},{"__ignoreMap":165},[629],{"type":39,"tag":225,"props":630,"children":631},{"class":227,"line":228},[632,636,640],{"type":39,"tag":225,"props":633,"children":634},{"style":494},[635],{"type":45,"value":497},{"type":39,"tag":225,"props":637,"children":638},{"style":500},[639],{"type":45,"value":503},{"type":39,"tag":225,"props":641,"children":642},{"style":500},[643],{"type":45,"value":508},{"type":39,"tag":55,"props":645,"children":646},{},[647],{"type":45,"value":513},{"type":39,"tag":94,"props":649,"children":650},{},[651,656,661],{"type":39,"tag":98,"props":652,"children":653},{},[654],{"type":45,"value":655},"Test passes",{"type":39,"tag":98,"props":657,"children":658},{},[659],{"type":45,"value":660},"Other tests still pass",{"type":39,"tag":98,"props":662,"children":663},{},[664],{"type":45,"value":665},"Output pristine (no errors, warnings)",{"type":39,"tag":55,"props":667,"children":668},{},[669,674],{"type":39,"tag":64,"props":670,"children":671},{},[672],{"type":45,"value":673},"Test fails?",{"type":45,"value":675}," Fix code, not test.",{"type":39,"tag":55,"props":677,"children":678},{},[679,684],{"type":39,"tag":64,"props":680,"children":681},{},[682],{"type":45,"value":683},"Other tests fail?",{"type":45,"value":685}," Fix now.",{"type":39,"tag":399,"props":687,"children":689},{"id":688},"refactor-clean-up",[690],{"type":45,"value":691},"REFACTOR - Clean Up",{"type":39,"tag":55,"props":693,"children":694},{},[695],{"type":45,"value":696},"After green only:",{"type":39,"tag":94,"props":698,"children":699},{},[700,705,710],{"type":39,"tag":98,"props":701,"children":702},{},[703],{"type":45,"value":704},"Remove duplication",{"type":39,"tag":98,"props":706,"children":707},{},[708],{"type":45,"value":709},"Improve names",{"type":39,"tag":98,"props":711,"children":712},{},[713],{"type":45,"value":714},"Extract helpers",{"type":39,"tag":55,"props":716,"children":717},{},[718],{"type":45,"value":719},"Keep tests green. Don't add behavior.",{"type":39,"tag":399,"props":721,"children":723},{"id":722},"repeat",[724],{"type":45,"value":725},"Repeat",{"type":39,"tag":55,"props":727,"children":728},{},[729],{"type":45,"value":730},"Next failing test for next feature.",{"type":39,"tag":48,"props":732,"children":734},{"id":733},"good-tests",[735],{"type":45,"value":736},"Good Tests",{"type":39,"tag":738,"props":739,"children":740},"table",{},[741,765],{"type":39,"tag":742,"props":743,"children":744},"thead",{},[745],{"type":39,"tag":746,"props":747,"children":748},"tr",{},[749,755,760],{"type":39,"tag":750,"props":751,"children":752},"th",{},[753],{"type":45,"value":754},"Quality",{"type":39,"tag":750,"props":756,"children":757},{},[758],{"type":45,"value":759},"Good",{"type":39,"tag":750,"props":761,"children":762},{},[763],{"type":45,"value":764},"Bad",{"type":39,"tag":766,"props":767,"children":768},"tbody",{},[769,795,820],{"type":39,"tag":746,"props":770,"children":771},{},[772,781,786],{"type":39,"tag":773,"props":774,"children":775},"td",{},[776],{"type":39,"tag":64,"props":777,"children":778},{},[779],{"type":45,"value":780},"Minimal",{"type":39,"tag":773,"props":782,"children":783},{},[784],{"type":45,"value":785},"One thing. \"and\" in name? Split it.",{"type":39,"tag":773,"props":787,"children":788},{},[789],{"type":39,"tag":163,"props":790,"children":792},{"className":791},[],[793],{"type":45,"value":794},"test('validates email and domain and whitespace')",{"type":39,"tag":746,"props":796,"children":797},{},[798,806,811],{"type":39,"tag":773,"props":799,"children":800},{},[801],{"type":39,"tag":64,"props":802,"children":803},{},[804],{"type":45,"value":805},"Clear",{"type":39,"tag":773,"props":807,"children":808},{},[809],{"type":45,"value":810},"Name describes behavior",{"type":39,"tag":773,"props":812,"children":813},{},[814],{"type":39,"tag":163,"props":815,"children":817},{"className":816},[],[818],{"type":45,"value":819},"test('test1')",{"type":39,"tag":746,"props":821,"children":822},{},[823,831,836],{"type":39,"tag":773,"props":824,"children":825},{},[826],{"type":39,"tag":64,"props":827,"children":828},{},[829],{"type":45,"value":830},"Shows intent",{"type":39,"tag":773,"props":832,"children":833},{},[834],{"type":45,"value":835},"Demonstrates desired API",{"type":39,"tag":773,"props":837,"children":838},{},[839],{"type":45,"value":840},"Obscures what code should do",{"type":39,"tag":48,"props":842,"children":844},{"id":843},"why-order-matters",[845],{"type":45,"value":846},"Why Order Matters",{"type":39,"tag":55,"props":848,"children":849},{},[850],{"type":39,"tag":64,"props":851,"children":852},{},[853],{"type":45,"value":854},"\"I'll write tests after to verify it works\"",{"type":39,"tag":55,"props":856,"children":857},{},[858],{"type":45,"value":859},"Tests written after code pass immediately. Passing immediately proves nothing:",{"type":39,"tag":94,"props":861,"children":862},{},[863,868,873,878],{"type":39,"tag":98,"props":864,"children":865},{},[866],{"type":45,"value":867},"Might test wrong thing",{"type":39,"tag":98,"props":869,"children":870},{},[871],{"type":45,"value":872},"Might test implementation, not behavior",{"type":39,"tag":98,"props":874,"children":875},{},[876],{"type":45,"value":877},"Might miss edge cases you forgot",{"type":39,"tag":98,"props":879,"children":880},{},[881],{"type":45,"value":882},"You never saw it catch the bug",{"type":39,"tag":55,"props":884,"children":885},{},[886],{"type":45,"value":887},"Test-first forces you to see the test fail, proving it actually tests something.",{"type":39,"tag":55,"props":889,"children":890},{},[891],{"type":39,"tag":64,"props":892,"children":893},{},[894],{"type":45,"value":895},"\"I already manually tested all the edge cases\"",{"type":39,"tag":55,"props":897,"children":898},{},[899],{"type":45,"value":900},"Manual testing is ad-hoc. You think you tested everything but:",{"type":39,"tag":94,"props":902,"children":903},{},[904,909,914,919],{"type":39,"tag":98,"props":905,"children":906},{},[907],{"type":45,"value":908},"No record of what you tested",{"type":39,"tag":98,"props":910,"children":911},{},[912],{"type":45,"value":913},"Can't re-run when code changes",{"type":39,"tag":98,"props":915,"children":916},{},[917],{"type":45,"value":918},"Easy to forget cases under pressure",{"type":39,"tag":98,"props":920,"children":921},{},[922],{"type":45,"value":923},"\"It worked when I tried it\" ≠ comprehensive",{"type":39,"tag":55,"props":925,"children":926},{},[927],{"type":45,"value":928},"Automated tests are systematic. They run the same way every time.",{"type":39,"tag":55,"props":930,"children":931},{},[932],{"type":39,"tag":64,"props":933,"children":934},{},[935],{"type":45,"value":936},"\"Deleting X hours of work is wasteful\"",{"type":39,"tag":55,"props":938,"children":939},{},[940],{"type":45,"value":941},"Sunk cost fallacy. The time is already gone. Your choice now:",{"type":39,"tag":94,"props":943,"children":944},{},[945,950],{"type":39,"tag":98,"props":946,"children":947},{},[948],{"type":45,"value":949},"Delete and rewrite with TDD (X more hours, high confidence)",{"type":39,"tag":98,"props":951,"children":952},{},[953],{"type":45,"value":954},"Keep it and add tests after (30 min, low confidence, likely bugs)",{"type":39,"tag":55,"props":956,"children":957},{},[958],{"type":45,"value":959},"The \"waste\" is keeping code you can't trust. Working code without real tests is technical debt.",{"type":39,"tag":55,"props":961,"children":962},{},[963],{"type":39,"tag":64,"props":964,"children":965},{},[966],{"type":45,"value":967},"\"TDD is dogmatic, being pragmatic means adapting\"",{"type":39,"tag":55,"props":969,"children":970},{},[971],{"type":45,"value":972},"TDD IS pragmatic:",{"type":39,"tag":94,"props":974,"children":975},{},[976,981,986,991],{"type":39,"tag":98,"props":977,"children":978},{},[979],{"type":45,"value":980},"Finds bugs before commit (faster than debugging after)",{"type":39,"tag":98,"props":982,"children":983},{},[984],{"type":45,"value":985},"Prevents regressions (tests catch breaks immediately)",{"type":39,"tag":98,"props":987,"children":988},{},[989],{"type":45,"value":990},"Documents behavior (tests show how to use code)",{"type":39,"tag":98,"props":992,"children":993},{},[994],{"type":45,"value":995},"Enables refactoring (change freely, tests catch breaks)",{"type":39,"tag":55,"props":997,"children":998},{},[999],{"type":45,"value":1000},"\"Pragmatic\" shortcuts = debugging in production = slower.",{"type":39,"tag":55,"props":1002,"children":1003},{},[1004],{"type":39,"tag":64,"props":1005,"children":1006},{},[1007],{"type":45,"value":1008},"\"Tests after achieve the same goals - it's spirit not ritual\"",{"type":39,"tag":55,"props":1010,"children":1011},{},[1012],{"type":45,"value":1013},"No. Tests-after answer \"What does this do?\" Tests-first answer \"What should this do?\"",{"type":39,"tag":55,"props":1015,"children":1016},{},[1017],{"type":45,"value":1018},"Tests-after are biased by your implementation. You test what you built, not what's required. You verify remembered edge cases, not discovered ones.",{"type":39,"tag":55,"props":1020,"children":1021},{},[1022],{"type":45,"value":1023},"Tests-first force edge case discovery before implementing. Tests-after verify you remembered everything (you didn't).",{"type":39,"tag":55,"props":1025,"children":1026},{},[1027],{"type":45,"value":1028},"30 minutes of tests after ≠ TDD. You get coverage, lose proof tests work.",{"type":39,"tag":48,"props":1030,"children":1032},{"id":1031},"common-rationalizations",[1033],{"type":45,"value":1034},"Common Rationalizations",{"type":39,"tag":738,"props":1036,"children":1037},{},[1038,1054],{"type":39,"tag":742,"props":1039,"children":1040},{},[1041],{"type":39,"tag":746,"props":1042,"children":1043},{},[1044,1049],{"type":39,"tag":750,"props":1045,"children":1046},{},[1047],{"type":45,"value":1048},"Excuse",{"type":39,"tag":750,"props":1050,"children":1051},{},[1052],{"type":45,"value":1053},"Reality",{"type":39,"tag":766,"props":1055,"children":1056},{},[1057,1070,1083,1096,1109,1122,1135,1148,1161,1174,1187],{"type":39,"tag":746,"props":1058,"children":1059},{},[1060,1065],{"type":39,"tag":773,"props":1061,"children":1062},{},[1063],{"type":45,"value":1064},"\"Too simple to test\"",{"type":39,"tag":773,"props":1066,"children":1067},{},[1068],{"type":45,"value":1069},"Simple code breaks. Test takes 30 seconds.",{"type":39,"tag":746,"props":1071,"children":1072},{},[1073,1078],{"type":39,"tag":773,"props":1074,"children":1075},{},[1076],{"type":45,"value":1077},"\"I'll test after\"",{"type":39,"tag":773,"props":1079,"children":1080},{},[1081],{"type":45,"value":1082},"Tests passing immediately prove nothing.",{"type":39,"tag":746,"props":1084,"children":1085},{},[1086,1091],{"type":39,"tag":773,"props":1087,"children":1088},{},[1089],{"type":45,"value":1090},"\"Tests after achieve same goals\"",{"type":39,"tag":773,"props":1092,"children":1093},{},[1094],{"type":45,"value":1095},"Tests-after = \"what does this do?\" Tests-first = \"what should this do?\"",{"type":39,"tag":746,"props":1097,"children":1098},{},[1099,1104],{"type":39,"tag":773,"props":1100,"children":1101},{},[1102],{"type":45,"value":1103},"\"Already manually tested\"",{"type":39,"tag":773,"props":1105,"children":1106},{},[1107],{"type":45,"value":1108},"Ad-hoc ≠ systematic. No record, can't re-run.",{"type":39,"tag":746,"props":1110,"children":1111},{},[1112,1117],{"type":39,"tag":773,"props":1113,"children":1114},{},[1115],{"type":45,"value":1116},"\"Deleting X hours is wasteful\"",{"type":39,"tag":773,"props":1118,"children":1119},{},[1120],{"type":45,"value":1121},"Sunk cost fallacy. Keeping unverified code is technical debt.",{"type":39,"tag":746,"props":1123,"children":1124},{},[1125,1130],{"type":39,"tag":773,"props":1126,"children":1127},{},[1128],{"type":45,"value":1129},"\"Keep as reference, write tests first\"",{"type":39,"tag":773,"props":1131,"children":1132},{},[1133],{"type":45,"value":1134},"You'll adapt it. That's testing after. Delete means delete.",{"type":39,"tag":746,"props":1136,"children":1137},{},[1138,1143],{"type":39,"tag":773,"props":1139,"children":1140},{},[1141],{"type":45,"value":1142},"\"Need to explore first\"",{"type":39,"tag":773,"props":1144,"children":1145},{},[1146],{"type":45,"value":1147},"Fine. Throw away exploration, start with TDD.",{"type":39,"tag":746,"props":1149,"children":1150},{},[1151,1156],{"type":39,"tag":773,"props":1152,"children":1153},{},[1154],{"type":45,"value":1155},"\"Test hard = design unclear\"",{"type":39,"tag":773,"props":1157,"children":1158},{},[1159],{"type":45,"value":1160},"Listen to test. Hard to test = hard to use.",{"type":39,"tag":746,"props":1162,"children":1163},{},[1164,1169],{"type":39,"tag":773,"props":1165,"children":1166},{},[1167],{"type":45,"value":1168},"\"TDD will slow me down\"",{"type":39,"tag":773,"props":1170,"children":1171},{},[1172],{"type":45,"value":1173},"TDD faster than debugging. Pragmatic = test-first.",{"type":39,"tag":746,"props":1175,"children":1176},{},[1177,1182],{"type":39,"tag":773,"props":1178,"children":1179},{},[1180],{"type":45,"value":1181},"\"Manual test faster\"",{"type":39,"tag":773,"props":1183,"children":1184},{},[1185],{"type":45,"value":1186},"Manual doesn't prove edge cases. You'll re-test every change.",{"type":39,"tag":746,"props":1188,"children":1189},{},[1190,1195],{"type":39,"tag":773,"props":1191,"children":1192},{},[1193],{"type":45,"value":1194},"\"Existing code has no tests\"",{"type":39,"tag":773,"props":1196,"children":1197},{},[1198],{"type":45,"value":1199},"You're improving it. Add tests for existing code.",{"type":39,"tag":48,"props":1201,"children":1203},{"id":1202},"red-flags-stop-and-start-over",[1204],{"type":45,"value":1205},"Red Flags - STOP and Start Over",{"type":39,"tag":94,"props":1207,"children":1208},{},[1209,1214,1219,1224,1229,1234,1239,1244,1249,1254,1259,1264,1269],{"type":39,"tag":98,"props":1210,"children":1211},{},[1212],{"type":45,"value":1213},"Code before test",{"type":39,"tag":98,"props":1215,"children":1216},{},[1217],{"type":45,"value":1218},"Test after implementation",{"type":39,"tag":98,"props":1220,"children":1221},{},[1222],{"type":45,"value":1223},"Test passes immediately",{"type":39,"tag":98,"props":1225,"children":1226},{},[1227],{"type":45,"value":1228},"Can't explain why test failed",{"type":39,"tag":98,"props":1230,"children":1231},{},[1232],{"type":45,"value":1233},"Tests added \"later\"",{"type":39,"tag":98,"props":1235,"children":1236},{},[1237],{"type":45,"value":1238},"Rationalizing \"just this once\"",{"type":39,"tag":98,"props":1240,"children":1241},{},[1242],{"type":45,"value":1243},"\"I already manually tested it\"",{"type":39,"tag":98,"props":1245,"children":1246},{},[1247],{"type":45,"value":1248},"\"Tests after achieve the same purpose\"",{"type":39,"tag":98,"props":1250,"children":1251},{},[1252],{"type":45,"value":1253},"\"It's about spirit not ritual\"",{"type":39,"tag":98,"props":1255,"children":1256},{},[1257],{"type":45,"value":1258},"\"Keep as reference\" or \"adapt existing code\"",{"type":39,"tag":98,"props":1260,"children":1261},{},[1262],{"type":45,"value":1263},"\"Already spent X hours, deleting is wasteful\"",{"type":39,"tag":98,"props":1265,"children":1266},{},[1267],{"type":45,"value":1268},"\"TDD is dogmatic, I'm being pragmatic\"",{"type":39,"tag":98,"props":1270,"children":1271},{},[1272],{"type":45,"value":1273},"\"This is different because...\"",{"type":39,"tag":55,"props":1275,"children":1276},{},[1277],{"type":39,"tag":64,"props":1278,"children":1279},{},[1280],{"type":45,"value":1281},"All of these mean: Delete code. Start over with TDD.",{"type":39,"tag":48,"props":1283,"children":1285},{"id":1284},"example-bug-fix",[1286],{"type":45,"value":1287},"Example: Bug Fix",{"type":39,"tag":55,"props":1289,"children":1290},{},[1291,1296],{"type":39,"tag":64,"props":1292,"children":1293},{},[1294],{"type":45,"value":1295},"Bug:",{"type":45,"value":1297}," Empty email accepted",{"type":39,"tag":55,"props":1299,"children":1300},{},[1301],{"type":39,"tag":64,"props":1302,"children":1303},{},[1304],{"type":45,"value":1305},"RED",{"type":39,"tag":156,"props":1307,"children":1311},{"className":1308,"code":1309,"language":1310,"meta":165,"style":165},"language-typescript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","test('rejects empty email', async () => {\n  const result = await submitForm({ email: '' });\n  expect(result.error).toBe('Email required');\n});\n","typescript",[1312],{"type":39,"tag":163,"props":1313,"children":1314},{"__ignoreMap":165},[1315,1371,1440,1505],{"type":39,"tag":225,"props":1316,"children":1317},{"class":227,"line":228},[1318,1324,1330,1336,1341,1345,1350,1356,1361,1366],{"type":39,"tag":225,"props":1319,"children":1321},{"style":1320},"--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF",[1322],{"type":45,"value":1323},"test",{"type":39,"tag":225,"props":1325,"children":1327},{"style":1326},"--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8",[1328],{"type":45,"value":1329},"(",{"type":39,"tag":225,"props":1331,"children":1333},{"style":1332},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF",[1334],{"type":45,"value":1335},"'",{"type":39,"tag":225,"props":1337,"children":1338},{"style":500},[1339],{"type":45,"value":1340},"rejects empty email",{"type":39,"tag":225,"props":1342,"children":1343},{"style":1332},[1344],{"type":45,"value":1335},{"type":39,"tag":225,"props":1346,"children":1347},{"style":1332},[1348],{"type":45,"value":1349},",",{"type":39,"tag":225,"props":1351,"children":1353},{"style":1352},"--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA",[1354],{"type":45,"value":1355}," async",{"type":39,"tag":225,"props":1357,"children":1358},{"style":1332},[1359],{"type":45,"value":1360}," ()",{"type":39,"tag":225,"props":1362,"children":1363},{"style":1352},[1364],{"type":45,"value":1365}," =>",{"type":39,"tag":225,"props":1367,"children":1368},{"style":1332},[1369],{"type":45,"value":1370}," {\n",{"type":39,"tag":225,"props":1372,"children":1373},{"class":227,"line":237},[1374,1379,1384,1389,1395,1400,1405,1410,1415,1420,1425,1430,1435],{"type":39,"tag":225,"props":1375,"children":1376},{"style":1352},[1377],{"type":45,"value":1378},"  const",{"type":39,"tag":225,"props":1380,"children":1381},{"style":1326},[1382],{"type":45,"value":1383}," result",{"type":39,"tag":225,"props":1385,"children":1386},{"style":1332},[1387],{"type":45,"value":1388}," =",{"type":39,"tag":225,"props":1390,"children":1392},{"style":1391},"--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic",[1393],{"type":45,"value":1394}," await",{"type":39,"tag":225,"props":1396,"children":1397},{"style":1320},[1398],{"type":45,"value":1399}," submitForm",{"type":39,"tag":225,"props":1401,"children":1403},{"style":1402},"--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178",[1404],{"type":45,"value":1329},{"type":39,"tag":225,"props":1406,"children":1407},{"style":1332},[1408],{"type":45,"value":1409},"{",{"type":39,"tag":225,"props":1411,"children":1412},{"style":1402},[1413],{"type":45,"value":1414}," email",{"type":39,"tag":225,"props":1416,"children":1417},{"style":1332},[1418],{"type":45,"value":1419},":",{"type":39,"tag":225,"props":1421,"children":1422},{"style":1332},[1423],{"type":45,"value":1424}," ''",{"type":39,"tag":225,"props":1426,"children":1427},{"style":1332},[1428],{"type":45,"value":1429}," }",{"type":39,"tag":225,"props":1431,"children":1432},{"style":1402},[1433],{"type":45,"value":1434},")",{"type":39,"tag":225,"props":1436,"children":1437},{"style":1332},[1438],{"type":45,"value":1439},";\n",{"type":39,"tag":225,"props":1441,"children":1442},{"class":227,"line":246},[1443,1448,1452,1457,1462,1467,1471,1475,1480,1484,1488,1493,1497,1501],{"type":39,"tag":225,"props":1444,"children":1445},{"style":1320},[1446],{"type":45,"value":1447},"  expect",{"type":39,"tag":225,"props":1449,"children":1450},{"style":1402},[1451],{"type":45,"value":1329},{"type":39,"tag":225,"props":1453,"children":1454},{"style":1326},[1455],{"type":45,"value":1456},"result",{"type":39,"tag":225,"props":1458,"children":1459},{"style":1332},[1460],{"type":45,"value":1461},".",{"type":39,"tag":225,"props":1463,"children":1464},{"style":1326},[1465],{"type":45,"value":1466},"error",{"type":39,"tag":225,"props":1468,"children":1469},{"style":1402},[1470],{"type":45,"value":1434},{"type":39,"tag":225,"props":1472,"children":1473},{"style":1332},[1474],{"type":45,"value":1461},{"type":39,"tag":225,"props":1476,"children":1477},{"style":1320},[1478],{"type":45,"value":1479},"toBe",{"type":39,"tag":225,"props":1481,"children":1482},{"style":1402},[1483],{"type":45,"value":1329},{"type":39,"tag":225,"props":1485,"children":1486},{"style":1332},[1487],{"type":45,"value":1335},{"type":39,"tag":225,"props":1489,"children":1490},{"style":500},[1491],{"type":45,"value":1492},"Email required",{"type":39,"tag":225,"props":1494,"children":1495},{"style":1332},[1496],{"type":45,"value":1335},{"type":39,"tag":225,"props":1498,"children":1499},{"style":1402},[1500],{"type":45,"value":1434},{"type":39,"tag":225,"props":1502,"children":1503},{"style":1332},[1504],{"type":45,"value":1439},{"type":39,"tag":225,"props":1506,"children":1507},{"class":227,"line":255},[1508,1513,1517],{"type":39,"tag":225,"props":1509,"children":1510},{"style":1332},[1511],{"type":45,"value":1512},"}",{"type":39,"tag":225,"props":1514,"children":1515},{"style":1326},[1516],{"type":45,"value":1434},{"type":39,"tag":225,"props":1518,"children":1519},{"style":1332},[1520],{"type":45,"value":1439},{"type":39,"tag":55,"props":1522,"children":1523},{},[1524],{"type":39,"tag":64,"props":1525,"children":1526},{},[1527],{"type":45,"value":1528},"Verify RED",{"type":39,"tag":156,"props":1530,"children":1532},{"className":482,"code":1531,"language":484,"meta":165,"style":165},"$ npm test\nFAIL: expected 'Email required', got undefined\n",[1533],{"type":39,"tag":163,"props":1534,"children":1535},{"__ignoreMap":165},[1536,1554],{"type":39,"tag":225,"props":1537,"children":1538},{"class":227,"line":228},[1539,1544,1549],{"type":39,"tag":225,"props":1540,"children":1541},{"style":494},[1542],{"type":45,"value":1543},"$",{"type":39,"tag":225,"props":1545,"children":1546},{"style":500},[1547],{"type":45,"value":1548}," npm",{"type":39,"tag":225,"props":1550,"children":1551},{"style":500},[1552],{"type":45,"value":1553}," test\n",{"type":39,"tag":225,"props":1555,"children":1556},{"class":227,"line":237},[1557,1562,1567,1572,1576,1580,1584,1589],{"type":39,"tag":225,"props":1558,"children":1559},{"style":494},[1560],{"type":45,"value":1561},"FAIL:",{"type":39,"tag":225,"props":1563,"children":1564},{"style":500},[1565],{"type":45,"value":1566}," expected",{"type":39,"tag":225,"props":1568,"children":1569},{"style":1332},[1570],{"type":45,"value":1571}," '",{"type":39,"tag":225,"props":1573,"children":1574},{"style":500},[1575],{"type":45,"value":1492},{"type":39,"tag":225,"props":1577,"children":1578},{"style":1332},[1579],{"type":45,"value":1335},{"type":39,"tag":225,"props":1581,"children":1582},{"style":500},[1583],{"type":45,"value":1349},{"type":39,"tag":225,"props":1585,"children":1586},{"style":500},[1587],{"type":45,"value":1588}," got",{"type":39,"tag":225,"props":1590,"children":1591},{"style":500},[1592],{"type":45,"value":1593}," undefined\n",{"type":39,"tag":55,"props":1595,"children":1596},{},[1597],{"type":39,"tag":64,"props":1598,"children":1599},{},[1600],{"type":45,"value":1601},"GREEN",{"type":39,"tag":156,"props":1603,"children":1605},{"className":1308,"code":1604,"language":1310,"meta":165,"style":165},"function submitForm(data: FormData) {\n  if (!data.email?.trim()) {\n    return { error: 'Email required' };\n  }\n  \u002F\u002F ...\n}\n",[1606],{"type":39,"tag":163,"props":1607,"children":1608},{"__ignoreMap":165},[1609,1648,1699,1738,1746,1755],{"type":39,"tag":225,"props":1610,"children":1611},{"class":227,"line":228},[1612,1617,1621,1625,1631,1635,1640,1644],{"type":39,"tag":225,"props":1613,"children":1614},{"style":1352},[1615],{"type":45,"value":1616},"function",{"type":39,"tag":225,"props":1618,"children":1619},{"style":1320},[1620],{"type":45,"value":1399},{"type":39,"tag":225,"props":1622,"children":1623},{"style":1332},[1624],{"type":45,"value":1329},{"type":39,"tag":225,"props":1626,"children":1628},{"style":1627},"--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic",[1629],{"type":45,"value":1630},"data",{"type":39,"tag":225,"props":1632,"children":1633},{"style":1332},[1634],{"type":45,"value":1419},{"type":39,"tag":225,"props":1636,"children":1637},{"style":494},[1638],{"type":45,"value":1639}," FormData",{"type":39,"tag":225,"props":1641,"children":1642},{"style":1332},[1643],{"type":45,"value":1434},{"type":39,"tag":225,"props":1645,"children":1646},{"style":1332},[1647],{"type":45,"value":1370},{"type":39,"tag":225,"props":1649,"children":1650},{"class":227,"line":237},[1651,1656,1661,1666,1670,1674,1679,1684,1689,1694],{"type":39,"tag":225,"props":1652,"children":1653},{"style":1391},[1654],{"type":45,"value":1655},"  if",{"type":39,"tag":225,"props":1657,"children":1658},{"style":1402},[1659],{"type":45,"value":1660}," (",{"type":39,"tag":225,"props":1662,"children":1663},{"style":1332},[1664],{"type":45,"value":1665},"!",{"type":39,"tag":225,"props":1667,"children":1668},{"style":1326},[1669],{"type":45,"value":1630},{"type":39,"tag":225,"props":1671,"children":1672},{"style":1332},[1673],{"type":45,"value":1461},{"type":39,"tag":225,"props":1675,"children":1676},{"style":1326},[1677],{"type":45,"value":1678},"email",{"type":39,"tag":225,"props":1680,"children":1681},{"style":1332},[1682],{"type":45,"value":1683},"?.",{"type":39,"tag":225,"props":1685,"children":1686},{"style":1320},[1687],{"type":45,"value":1688},"trim",{"type":39,"tag":225,"props":1690,"children":1691},{"style":1402},[1692],{"type":45,"value":1693},"()) ",{"type":39,"tag":225,"props":1695,"children":1696},{"style":1332},[1697],{"type":45,"value":1698},"{\n",{"type":39,"tag":225,"props":1700,"children":1701},{"class":227,"line":246},[1702,1707,1712,1717,1721,1725,1729,1733],{"type":39,"tag":225,"props":1703,"children":1704},{"style":1391},[1705],{"type":45,"value":1706},"    return",{"type":39,"tag":225,"props":1708,"children":1709},{"style":1332},[1710],{"type":45,"value":1711}," {",{"type":39,"tag":225,"props":1713,"children":1714},{"style":1402},[1715],{"type":45,"value":1716}," error",{"type":39,"tag":225,"props":1718,"children":1719},{"style":1332},[1720],{"type":45,"value":1419},{"type":39,"tag":225,"props":1722,"children":1723},{"style":1332},[1724],{"type":45,"value":1571},{"type":39,"tag":225,"props":1726,"children":1727},{"style":500},[1728],{"type":45,"value":1492},{"type":39,"tag":225,"props":1730,"children":1731},{"style":1332},[1732],{"type":45,"value":1335},{"type":39,"tag":225,"props":1734,"children":1735},{"style":1332},[1736],{"type":45,"value":1737}," };\n",{"type":39,"tag":225,"props":1739,"children":1740},{"class":227,"line":255},[1741],{"type":39,"tag":225,"props":1742,"children":1743},{"style":1332},[1744],{"type":45,"value":1745},"  }\n",{"type":39,"tag":225,"props":1747,"children":1748},{"class":227,"line":264},[1749],{"type":39,"tag":225,"props":1750,"children":1752},{"style":1751},"--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic",[1753],{"type":45,"value":1754},"  \u002F\u002F ...\n",{"type":39,"tag":225,"props":1756,"children":1757},{"class":227,"line":273},[1758],{"type":39,"tag":225,"props":1759,"children":1760},{"style":1332},[1761],{"type":45,"value":397},{"type":39,"tag":55,"props":1763,"children":1764},{},[1765],{"type":39,"tag":64,"props":1766,"children":1767},{},[1768],{"type":45,"value":1769},"Verify GREEN",{"type":39,"tag":156,"props":1771,"children":1773},{"className":482,"code":1772,"language":484,"meta":165,"style":165},"$ npm test\nPASS\n",[1774],{"type":39,"tag":163,"props":1775,"children":1776},{"__ignoreMap":165},[1777,1792],{"type":39,"tag":225,"props":1778,"children":1779},{"class":227,"line":228},[1780,1784,1788],{"type":39,"tag":225,"props":1781,"children":1782},{"style":494},[1783],{"type":45,"value":1543},{"type":39,"tag":225,"props":1785,"children":1786},{"style":500},[1787],{"type":45,"value":1548},{"type":39,"tag":225,"props":1789,"children":1790},{"style":500},[1791],{"type":45,"value":1553},{"type":39,"tag":225,"props":1793,"children":1794},{"class":227,"line":237},[1795],{"type":39,"tag":225,"props":1796,"children":1797},{"style":494},[1798],{"type":45,"value":1799},"PASS\n",{"type":39,"tag":55,"props":1801,"children":1802},{},[1803,1808],{"type":39,"tag":64,"props":1804,"children":1805},{},[1806],{"type":45,"value":1807},"REFACTOR",{"type":45,"value":1809},"\nExtract validation for multiple fields if needed.",{"type":39,"tag":48,"props":1811,"children":1813},{"id":1812},"verification-checklist",[1814],{"type":45,"value":1815},"Verification Checklist",{"type":39,"tag":55,"props":1817,"children":1818},{},[1819],{"type":45,"value":1820},"Before marking work complete:",{"type":39,"tag":94,"props":1822,"children":1825},{"className":1823},[1824],"contains-task-list",[1826,1838,1847,1856,1865,1874,1883,1892],{"type":39,"tag":98,"props":1827,"children":1830},{"className":1828},[1829],"task-list-item",[1831,1836],{"type":39,"tag":1832,"props":1833,"children":1835},"input",{"disabled":304,"type":1834},"checkbox",[],{"type":45,"value":1837}," Every new function\u002Fmethod has a test",{"type":39,"tag":98,"props":1839,"children":1841},{"className":1840},[1829],[1842,1845],{"type":39,"tag":1832,"props":1843,"children":1844},{"disabled":304,"type":1834},[],{"type":45,"value":1846}," Watched each test fail before implementing",{"type":39,"tag":98,"props":1848,"children":1850},{"className":1849},[1829],[1851,1854],{"type":39,"tag":1832,"props":1852,"children":1853},{"disabled":304,"type":1834},[],{"type":45,"value":1855}," Each test failed for expected reason (feature missing, not typo)",{"type":39,"tag":98,"props":1857,"children":1859},{"className":1858},[1829],[1860,1863],{"type":39,"tag":1832,"props":1861,"children":1862},{"disabled":304,"type":1834},[],{"type":45,"value":1864}," Wrote minimal code to pass each test",{"type":39,"tag":98,"props":1866,"children":1868},{"className":1867},[1829],[1869,1872],{"type":39,"tag":1832,"props":1870,"children":1871},{"disabled":304,"type":1834},[],{"type":45,"value":1873}," All tests pass",{"type":39,"tag":98,"props":1875,"children":1877},{"className":1876},[1829],[1878,1881],{"type":39,"tag":1832,"props":1879,"children":1880},{"disabled":304,"type":1834},[],{"type":45,"value":1882}," Output pristine (no errors, warnings)",{"type":39,"tag":98,"props":1884,"children":1886},{"className":1885},[1829],[1887,1890],{"type":39,"tag":1832,"props":1888,"children":1889},{"disabled":304,"type":1834},[],{"type":45,"value":1891}," Tests use real code (mocks only if unavoidable)",{"type":39,"tag":98,"props":1893,"children":1895},{"className":1894},[1829],[1896,1899],{"type":39,"tag":1832,"props":1897,"children":1898},{"disabled":304,"type":1834},[],{"type":45,"value":1900}," Edge cases and errors covered",{"type":39,"tag":55,"props":1902,"children":1903},{},[1904],{"type":45,"value":1905},"Can't check all boxes? You skipped TDD. Start over.",{"type":39,"tag":48,"props":1907,"children":1909},{"id":1908},"when-stuck",[1910],{"type":45,"value":1911},"When Stuck",{"type":39,"tag":738,"props":1913,"children":1914},{},[1915,1931],{"type":39,"tag":742,"props":1916,"children":1917},{},[1918],{"type":39,"tag":746,"props":1919,"children":1920},{},[1921,1926],{"type":39,"tag":750,"props":1922,"children":1923},{},[1924],{"type":45,"value":1925},"Problem",{"type":39,"tag":750,"props":1927,"children":1928},{},[1929],{"type":45,"value":1930},"Solution",{"type":39,"tag":766,"props":1932,"children":1933},{},[1934,1947,1960,1973],{"type":39,"tag":746,"props":1935,"children":1936},{},[1937,1942],{"type":39,"tag":773,"props":1938,"children":1939},{},[1940],{"type":45,"value":1941},"Don't know how to test",{"type":39,"tag":773,"props":1943,"children":1944},{},[1945],{"type":45,"value":1946},"Write wished-for API. Write assertion first. Ask your human partner.",{"type":39,"tag":746,"props":1948,"children":1949},{},[1950,1955],{"type":39,"tag":773,"props":1951,"children":1952},{},[1953],{"type":45,"value":1954},"Test too complicated",{"type":39,"tag":773,"props":1956,"children":1957},{},[1958],{"type":45,"value":1959},"Design too complicated. Simplify interface.",{"type":39,"tag":746,"props":1961,"children":1962},{},[1963,1968],{"type":39,"tag":773,"props":1964,"children":1965},{},[1966],{"type":45,"value":1967},"Must mock everything",{"type":39,"tag":773,"props":1969,"children":1970},{},[1971],{"type":45,"value":1972},"Code too coupled. Use dependency injection.",{"type":39,"tag":746,"props":1974,"children":1975},{},[1976,1981],{"type":39,"tag":773,"props":1977,"children":1978},{},[1979],{"type":45,"value":1980},"Test setup huge",{"type":39,"tag":773,"props":1982,"children":1983},{},[1984],{"type":45,"value":1985},"Extract helpers. Still complex? Simplify design.",{"type":39,"tag":48,"props":1987,"children":1989},{"id":1988},"debugging-integration",[1990],{"type":45,"value":1991},"Debugging Integration",{"type":39,"tag":55,"props":1993,"children":1994},{},[1995],{"type":45,"value":1996},"Bug found? Write failing test reproducing it. Follow TDD cycle. Test proves fix and prevents regression.",{"type":39,"tag":55,"props":1998,"children":1999},{},[2000],{"type":45,"value":2001},"Never fix bugs without a test.",{"type":39,"tag":48,"props":2003,"children":2005},{"id":2004},"testing-anti-patterns",[2006],{"type":45,"value":2007},"Testing Anti-Patterns",{"type":39,"tag":55,"props":2009,"children":2010},{},[2011],{"type":45,"value":2012},"When adding mocks or test utilities, read @testing-anti-patterns.md to avoid common pitfalls:",{"type":39,"tag":94,"props":2014,"children":2015},{},[2016,2021,2026],{"type":39,"tag":98,"props":2017,"children":2018},{},[2019],{"type":45,"value":2020},"Testing mock behavior instead of real behavior",{"type":39,"tag":98,"props":2022,"children":2023},{},[2024],{"type":45,"value":2025},"Adding test-only methods to production classes",{"type":39,"tag":98,"props":2027,"children":2028},{},[2029],{"type":45,"value":2030},"Mocking without understanding dependencies",{"type":39,"tag":48,"props":2032,"children":2034},{"id":2033},"final-rule",[2035],{"type":45,"value":2036},"Final Rule",{"type":39,"tag":156,"props":2038,"children":2041},{"className":2039,"code":2040,"language":45},[159],"Production code → test exists and failed first\nOtherwise → not TDD\n",[2042],{"type":39,"tag":163,"props":2043,"children":2044},{"__ignoreMap":165},[2045],{"type":45,"value":2040},{"type":39,"tag":55,"props":2047,"children":2048},{},[2049],{"type":45,"value":2050},"No exceptions without your human partner's permission.",{"type":39,"tag":2052,"props":2053,"children":2054},"style",{},[2055],{"type":45,"value":2056},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"items":2058,"total":2178},[2059,2078,2092,2104,2124,2146,2166],{"slug":2060,"name":2060,"fn":2061,"description":2062,"org":2063,"tags":2064,"stars":22,"repoUrl":23,"updatedAt":2077},"accessibility-and-inclusive-visualization","make data visualizations accessible","Make data visualizations accessible and inclusive. Use when the user needs chart or diagram accessibility guidance, text alternatives for complex visuals, color and contrast review, keyboard support, reduced-motion behavior for animation or parallax, or an accessibility QA workflow for exported figures, UML-like diagrams, and dashboards.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2065,2068,2071,2074],{"name":2066,"slug":2067,"type":15},"Accessibility","accessibility",{"name":2069,"slug":2070,"type":15},"Charts","charts",{"name":2072,"slug":2073,"type":15},"Data Visualization","data-visualization",{"name":2075,"slug":2076,"type":15},"Design","design","2026-06-30T19:00:57.102",{"slug":2079,"name":2079,"fn":2080,"description":2081,"org":2082,"tags":2083,"stars":22,"repoUrl":23,"updatedAt":2091},"agent-browser","automate browser interactions for agents","Browser automation CLI for AI agents. Use when the user needs to interact with websites, verify dev server output, test web apps, navigate pages, fill forms, click buttons, take screenshots, extract data, or automate any browser task. Also triggers when a dev server starts so you can verify it visually.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2084,2087,2090],{"name":2085,"slug":2086,"type":15},"Agents","agents",{"name":2088,"slug":2089,"type":15},"Browser Automation","browser-automation",{"name":20,"slug":21,"type":15},"2026-04-06T18:41:03.44016",{"slug":2093,"name":2093,"fn":2094,"description":2095,"org":2096,"tags":2097,"stars":22,"repoUrl":23,"updatedAt":2103},"agent-browser-verify","verify dev server output with automated browser","Automated browser verification for dev servers. Triggers when a dev server starts to run a visual gut-check with agent-browser — verifies the page loads, checks for console errors, validates key UI elements, and reports pass\u002Ffail before continuing.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2098,2099,2102],{"name":2088,"slug":2089,"type":15},{"name":2100,"slug":2101,"type":15},"Local Development","local-development",{"name":20,"slug":21,"type":15},"2026-04-06T18:41:17.526867",{"slug":2105,"name":2105,"fn":2106,"description":2107,"org":2108,"tags":2109,"stars":22,"repoUrl":23,"updatedAt":2123},"agents-sdk","build AI agents on Cloudflare Workers","Build AI agents on Cloudflare Workers using the Agents SDK. Load when creating stateful agents, durable workflows, real-time WebSocket apps, scheduled tasks, MCP servers, or chat applications. Covers Agent class, state management, callable RPC, Workflows integration, and React hooks. Biases towards retrieval from Cloudflare docs over pre-trained knowledge.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2110,2111,2114,2117,2120],{"name":2085,"slug":2086,"type":15},{"name":2112,"slug":2113,"type":15},"Cloudflare Workers","cloudflare-workers",{"name":2115,"slug":2116,"type":15},"SDK","sdk",{"name":2118,"slug":2119,"type":15},"Serverless","serverless",{"name":2121,"slug":2122,"type":15},"WebSockets","websockets","2026-04-06T18:39:51.717063",{"slug":2125,"name":2125,"fn":2126,"description":2127,"org":2128,"tags":2129,"stars":22,"repoUrl":23,"updatedAt":2145},"ai-elements","build chat UIs with AI Elements","AI Elements component library guidance — pre-built React components for AI interfaces built on shadcn\u002Fui. Use when building chat UIs, message displays, tool call rendering, streaming responses, reasoning panels, or any AI-native interface with the AI SDK.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2130,2133,2136,2139,2142],{"name":2131,"slug":2132,"type":15},"Frontend","frontend",{"name":2134,"slug":2135,"type":15},"React","react",{"name":2137,"slug":2138,"type":15},"shadcn\u002Fui","shadcn-ui",{"name":2140,"slug":2141,"type":15},"UI Components","ui-components",{"name":2143,"slug":2144,"type":15},"Vercel","vercel","2026-04-06T18:40:59.619419",{"slug":2147,"name":2147,"fn":2148,"description":2149,"org":2150,"tags":2151,"stars":22,"repoUrl":23,"updatedAt":2165},"ai-gateway","configure Vercel AI Gateway","Vercel AI Gateway expert guidance. Use when configuring model routing, provider failover, cost tracking, or managing multiple AI providers through a unified API.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2152,2155,2158,2161,2164],{"name":2153,"slug":2154,"type":15},"AI Infrastructure","ai-infrastructure",{"name":2156,"slug":2157,"type":15},"Cost Optimization","cost-optimization",{"name":2159,"slug":2160,"type":15},"LLM","llm",{"name":2162,"slug":2163,"type":15},"Performance","performance",{"name":2143,"slug":2144,"type":15},"2026-04-06T18:40:44.377464",{"slug":2167,"name":2167,"fn":2168,"description":2169,"org":2170,"tags":2171,"stars":22,"repoUrl":23,"updatedAt":2177},"ai-generation-persistence","implement persistence patterns for AI generations","AI generation persistence patterns — unique IDs, addressable URLs, database storage, and cost tracking for every LLM generation",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2172,2173,2176],{"name":2156,"slug":2157,"type":15},{"name":2174,"slug":2175,"type":15},"Database","database",{"name":2159,"slug":2160,"type":15},"2026-04-06T18:41:08.513425",600,{"items":2180,"total":2377},[2181,2202,2225,2242,2258,2275,2294,2306,2320,2334,2346,2361],{"slug":2182,"name":2182,"fn":2183,"description":2184,"org":2185,"tags":2186,"stars":2199,"repoUrl":2200,"updatedAt":2201},"prior-auth-packet-builder","build healthcare prior authorization packets","Build a concise prior authorization packet from local case files and payer policy docs.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2187,2190,2193,2196],{"name":2188,"slug":2189,"type":15},"Documents","documents",{"name":2191,"slug":2192,"type":15},"Healthcare","healthcare",{"name":2194,"slug":2195,"type":15},"Insurance","insurance",{"name":2197,"slug":2198,"type":15},"Regulatory Compliance","regulatory-compliance",28169,"https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-agents-python","2026-04-16T05:11:39.180399",{"slug":2203,"name":2203,"fn":2204,"description":2205,"org":2206,"tags":2207,"stars":2222,"repoUrl":2223,"updatedAt":2224},"aspnet-core","build ASP.NET Core web applications","Build, review, refactor, or architect ASP.NET Core web applications using current official guidance for .NET web development. Use when working on Blazor Web Apps, Razor Pages, MVC, Minimal APIs, controller-based Web APIs, SignalR, gRPC, middleware, dependency injection, configuration, authentication, authorization, testing, performance, deployment, or ASP.NET Core upgrades.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2208,2211,2213,2216,2219],{"name":2209,"slug":2210,"type":15},".NET","dotnet",{"name":2212,"slug":2203,"type":15},"ASP.NET Core",{"name":2214,"slug":2215,"type":15},"Blazor","blazor",{"name":2217,"slug":2218,"type":15},"C#","csharp",{"name":2220,"slug":2221,"type":15},"Web Development","web-development",23787,"https:\u002F\u002Fgithub.com\u002Fopenai\u002Fskills","2026-04-12T05:07:02.819491",{"slug":2226,"name":2226,"fn":2227,"description":2228,"org":2229,"tags":2230,"stars":2222,"repoUrl":2223,"updatedAt":2241},"chatgpt-apps","build ChatGPT Apps SDK applications","Build, scaffold, refactor, and troubleshoot ChatGPT Apps SDK applications that combine an MCP server and widget UI. Use when Codex needs to design tools, register UI resources, wire the MCP Apps bridge or ChatGPT compatibility APIs, apply Apps SDK metadata or CSP or domain settings, or produce a docs-aligned project scaffold. Prefer a docs-first workflow by invoking the openai-docs skill or OpenAI developer docs MCP tools before generating code.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2231,2234,2237,2240],{"name":2232,"slug":2233,"type":15},"Apps SDK","apps-sdk",{"name":2235,"slug":2236,"type":15},"ChatGPT","chatgpt",{"name":2238,"slug":2239,"type":15},"MCP","mcp",{"name":9,"slug":8,"type":15},"2026-04-12T05:07:05.468097",{"slug":2243,"name":2243,"fn":2244,"description":2245,"org":2246,"tags":2247,"stars":2222,"repoUrl":2223,"updatedAt":2257},"cli-creator","build CLIs from API docs","Build a composable CLI for Codex from API docs, an OpenAPI spec, existing curl examples, an SDK, a web app, an admin tool, or a local script. Use when the user wants Codex to create a command-line tool that can run from any repo, expose composable read\u002Fwrite commands, return stable JSON, manage auth, and pair with a companion skill.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2248,2251,2254],{"name":2249,"slug":2250,"type":15},"API Development","api-development",{"name":2252,"slug":2253,"type":15},"CLI","cli",{"name":2255,"slug":2256,"type":15},"Codex","codex","2026-04-12T05:07:04.132762",{"slug":2259,"name":2259,"fn":2260,"description":2261,"org":2262,"tags":2263,"stars":2222,"repoUrl":2223,"updatedAt":2274},"cloudflare-deploy","deploy projects to Cloudflare","Deploy applications and infrastructure to Cloudflare using Workers, Pages, and related platform services. Use when the user asks to deploy, host, publish, or set up a project on Cloudflare.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2264,2267,2270,2271],{"name":2265,"slug":2266,"type":15},"Cloudflare","cloudflare",{"name":2268,"slug":2269,"type":15},"Cloudflare Pages","cloudflare-pages",{"name":2112,"slug":2113,"type":15},{"name":2272,"slug":2273,"type":15},"Deployment","deployment","2026-04-12T05:07:14.275118",{"slug":2276,"name":2276,"fn":2277,"description":2278,"org":2279,"tags":2280,"stars":2222,"repoUrl":2223,"updatedAt":2293},"define-goal","define and set measurable project goals","Help the user define a concrete, measurable goal before starting work, especially when they ask to use the goal tool, create a goal, set an objective, clarify success criteria, or turn a fuzzy intention into a quantitative outcome. Use this skill for goal creation and goal refinement only; it does not manage durable snapshots, decision logs, or long-running execution artifacts.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2281,2284,2287,2290],{"name":2282,"slug":2283,"type":15},"Productivity","productivity",{"name":2285,"slug":2286,"type":15},"Project Management","project-management",{"name":2288,"slug":2289,"type":15},"Strategy","strategy",{"name":2291,"slug":2292,"type":15},"Task Management","task-management","2026-05-23T06:17:16.870838",{"slug":2295,"name":2295,"fn":2296,"description":2297,"org":2298,"tags":2299,"stars":2222,"repoUrl":2223,"updatedAt":2305},"figma","translate Figma designs into code","Use the Figma MCP server to fetch design context, screenshots, variables, and assets from Figma, and to translate Figma nodes into production code. Trigger when a task involves Figma URLs, node IDs, design-to-code implementation, or Figma MCP setup and troubleshooting.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2300,2301,2303,2304],{"name":2075,"slug":2076,"type":15},{"name":2302,"slug":2295,"type":15},"Figma",{"name":2131,"slug":2132,"type":15},{"name":2238,"slug":2239,"type":15},"2026-04-12T05:06:47.939943",{"slug":2307,"name":2307,"fn":2308,"description":2309,"org":2310,"tags":2311,"stars":2222,"repoUrl":2223,"updatedAt":2319},"figma-code-connect-components","connect Figma designs to code components","Connects Figma design components to code components using Code Connect mapping tools. Use when user says \"code connect\", \"connect this component to code\", \"map this component\", \"link component to code\", \"create code connect mapping\", or wants to establish mappings between Figma designs and code implementations. For canvas writes via `use_figma`, use `figma-use`.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2312,2313,2316,2317,2318],{"name":2075,"slug":2076,"type":15},{"name":2314,"slug":2315,"type":15},"Design System","design-system",{"name":2302,"slug":2295,"type":15},{"name":2131,"slug":2132,"type":15},{"name":2140,"slug":2141,"type":15},"2026-05-10T05:59:52.971881",{"slug":2321,"name":2321,"fn":2322,"description":2323,"org":2324,"tags":2325,"stars":2222,"repoUrl":2223,"updatedAt":2333},"figma-create-design-system-rules","generate design system rules from Figma","Generates custom design system rules for the user's codebase. Use when user says \"create design system rules\", \"generate rules for my project\", \"set up design rules\", \"customize design system guidelines\", or wants to establish project-specific conventions for Figma-to-code workflows. Requires Figma MCP server connection.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2326,2327,2328,2331,2332],{"name":2075,"slug":2076,"type":15},{"name":2314,"slug":2315,"type":15},{"name":2329,"slug":2330,"type":15},"Documentation","documentation",{"name":2302,"slug":2295,"type":15},{"name":2131,"slug":2132,"type":15},"2026-05-16T06:07:47.821474",{"slug":2335,"name":2335,"fn":2336,"description":2337,"org":2338,"tags":2339,"stars":2222,"repoUrl":2223,"updatedAt":2345},"figma-implement-design","translate Figma designs into application code","Translates Figma designs into production-ready application code with 1:1 visual fidelity. Use when implementing UI code from Figma files, when user mentions \"implement design\", \"generate code\", \"implement component\", provides Figma URLs, or asks to build components matching Figma specs. For Figma canvas writes via `use_figma`, use `figma-use`.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2340,2341,2342,2343,2344],{"name":2075,"slug":2076,"type":15},{"name":2302,"slug":2295,"type":15},{"name":2131,"slug":2132,"type":15},{"name":2140,"slug":2141,"type":15},{"name":2220,"slug":2221,"type":15},"2026-05-16T06:07:40.583615",{"slug":2347,"name":2347,"fn":2348,"description":2349,"org":2350,"tags":2351,"stars":2222,"repoUrl":2223,"updatedAt":2360},"hatch-pet","create animated pets for Codex","Create, repair, validate, visually QA, and package Codex-compatible animated pets and pet spritesheets from character art, generated images, company or prospect brand cues, or visual references. Use when a user wants a lightweight-worker Codex pet workflow, a non-pixel custom pet style, a prospect or company mascot pet, or a full 8x9 animated pet atlas with transparent unused cells, QA contact sheets, and pet.json packaging. This skill composes the installed $imagegen system skill for visual generation and uses bundled scripts for deterministic spritesheet assembly.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2352,2355,2356,2359],{"name":2353,"slug":2354,"type":15},"Animation","animation",{"name":2255,"slug":2256,"type":15},{"name":2357,"slug":2358,"type":15},"Creative","creative",{"name":2075,"slug":2076,"type":15},"2026-05-02T05:31:48.48485",{"slug":2362,"name":2362,"fn":2363,"description":2364,"org":2365,"tags":2366,"stars":2222,"repoUrl":2223,"updatedAt":2376},"imagegen","generate and edit raster images","Generate or edit raster images when the task benefits from AI-created bitmap visuals such as photos, illustrations, textures, sprites, mockups, or transparent-background cutouts. Use when Codex should create a brand-new image, transform an existing image, or derive visual variants from references, and the output should be a bitmap asset rather than repo-native code or vector. Do not use when the task is better handled by editing existing SVG\u002Fvector\u002Fcode-native assets, extending an established icon or logo system, or building the visual directly in HTML\u002FCSS\u002Fcanvas.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2367,2368,2369,2372,2375],{"name":2357,"slug":2358,"type":15},{"name":2075,"slug":2076,"type":15},{"name":2370,"slug":2371,"type":15},"Image Generation","image-generation",{"name":2373,"slug":2374,"type":15},"Images","images",{"name":9,"slug":8,"type":15},"2026-05-15T06:23:24.312127",675]