[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6CBAVC8K7ZXN7Q0Q3ZS3E19":3,"skill-same:01M6CBAVC8K7ZXN7Q0Q3ZS3E19":81},{"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":6,"sourceHtmlUrl":16,"categories":17,"keywords":26,"publishedAt":44,"linkOnly":45,"markdownContent":46,"markdownBody":47,"frontMatter":48,"refName":53,"commitSha":54,"skillDirectory":55,"forksCount":56,"repositoryHtmlUrl":57,"repositoryHomepageUrl":58,"ownerHtmlUrl":59,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":60,"install":61,"resources":74},"01M6CBAVC8K7ZXN7Q0Q3ZS3E19","test-driven-development",null,"Test-first implementation discipline: write the failing test, watch it fail, write minimal code to pass, refactor. Language- and framework-agnostic. Use when implementing any feature or bugfix, before writing implementation code.","shahboura\u002Fagents-opencode","shahboura","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F210767?v=4","01M6C6WKTBT0NH92BEPQRHQSYM","Shehab El Hadidy","01M6C6WKYXG8AE68MCGBNE5ZFR",2,"MIT","https:\u002F\u002Fgithub.com\u002Fshahboura\u002Fagents-opencode\u002Fblob\u002Fmain\u002F.opencode\u002Fskills\u002Ftest-driven-development\u002FSKILL.md",[18,23],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000008","测试与质量","SCENARIO","使用场景",{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000018","写作与文案",[27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43],"test","test driven development","development","implementation","writing","minimal","implementation discipline","opencode","superpowers","discipline","use","write","first","refactor","methodology","framework","code","2026-11-10 10:12:30",false,"---\nname: test-driven-development\ndescription: >-\n  Test-first implementation discipline: write the failing test, watch it fail,\n  write minimal code to pass, refactor. Language- and framework-agnostic. Use\n  when implementing any feature or bugfix, before writing implementation code.\nlicense: MIT\ncompatibility: opencode\nmetadata:\n  author: shahboura (methodology adapted from obra\u002Fsuperpowers, MIT)\n  version: \"1.0.0\"\n  audience: developers\n  workflow: development\n---\n\n# Test-Driven Development (TDD)\n\n## What I do\n\n- Enforce write-test-first: no production code without a failing test\n- Drive the RED → GREEN → REFACTOR cycle with verification at each step\n- Keep tests honest (see `references\u002Fwriting-good-tests.md`)\n\n## When to use me\n\n**Always:** new features, bug fixes, refactoring, behavior changes.\n\n**Exceptions (ask the user):** generated code, configuration files, throwaway\nprototypes. Visual\u002FUI work is not exempt by default — ask the user, and a\nPlaywright or screenshot regression check may substitute for a unit test.\n\nThinking \"skip TDD just this once\"? Stop — that is rationalization.\n\n## The Iron Law\n\n```\nNO PRODUCTION CODE WITHOUT A FAILING TEST FIRST\n```\n\nWrote code before the test — **code you wrote in this session and have not\ncommitted**? Delete it and start over: do not keep it as \"reference\", do not\nadapt it, do not look at it. Implement fresh from tests. Never delete\npre-existing, committed, or user-authored code; if the situation is unclear,\nask the user before removing anything.\n\n## The cycle\n\n1. **RED** — write one minimal test showing what should happen.\n2. **Verify RED** — run it and watch it fail for the expected reason (feature\n   missing, not a typo). A test that passes immediately is testing existing\n   behavior; fix the test.\n3. **GREEN** — write the simplest code that passes. No extra features, no refactoring beyond the test.\n4. **Verify GREEN** — run it; the new test passes and the project's suite stays\n   green. Run the project's own test command, not just your file, and report any\n   failure by name.\n5. **REFACTOR** — remove duplication, improve names, extract helpers; stay green; add no behavior.\n6. **Repeat** — next failing test for the next feature.\n\nCommits are a separate concern: follow the repository's review\u002Fcommit gate\nrather than committing once per cycle.\n\n### Good RED — clear name, real behavior, one thing\n\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```\n\n### Bad RED — vague name, tests the mock instead of the code\n\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```\n\n### Good GREEN — just enough to pass\n\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```\n\n### Bad GREEN — over-engineered beyond the test\n\n```typescript\nasync function retryOperation\u003CT>(\n  fn: () => Promise\u003CT>,\n  options?: { maxRetries?: number; backoff?: 'linear' | 'exponential'; onRetry?: (n: number) => void }\n): Promise\u003CT> { \u002F* YAGNI *\u002F }\n```\n\n## Good tests\n\n| Quality | Good | Bad |\n|---------|------|-----|\n| Minimal | One thing; \"and\" in the name → split it | `test('validates email and domain and whitespace')` |\n| Clear | Name describes the behavior | `test('test1')` |\n| Shows intent | Demonstrates the desired API | Obscures what the code should do |\n\nWhen writing or changing any test, read `references\u002Fwriting-good-tests.md`:\nname the break the test catches, derive expectations by hand, assert real\nbehavior (never the mock), and keep test-only code in test utilities.\n\n## Red flags — stop and start over\n\n- Code written before the test\n- Test passes immediately\n- Cannot explain why the test failed\n- \"I'll add tests later\" \u002F \"I already manually tested it\"\n- \"Keep as reference\" or \"adapt existing code\"\n- \"TDD is dogmatic, I'm being pragmatic\"\n\n## Common rationalizations\n\n| Excuse | Reality |\n|--------|---------|\n| \"Too simple to test\" | Simple code breaks; the test takes 30 seconds. |\n| \"I'll test after\" | Tests written after pass immediately — which proves nothing. |\n| \"Tests after achieve the same goal\" | Tests-after ask \"what does this do?\"; tests-first ask \"what should this do?\" |\n| \"Already manually tested\" | Manual testing is ad-hoc: no record, no re-run, easy to miss cases. |\n| \"Deleting hours of work is wasteful\" | Sunk cost — keeping code you cannot trust is the real waste. |\n| \"TDD slows me down\" | TDD catches bugs before commit and lets you refactor without fear. |\n\n## When stuck\n\n| Problem | Solution |\n|---------|----------|\n| Do not know how to test | Write the wished-for API; write the assertion first; ask the user. |\n| Test too complicated | The design is too complicated — simplify the interface. |\n| Must mock everything | The code is too coupled — use dependency injection. |\n\n## Debugging integration\n\nFound a bug? Write a failing test that reproduces it first, then follow the\ncycle — the test proves the fix and prevents regression. Security findings need\na regression test too: reproduce the flaw as a failing test before fixing it.\nSee `systematic-debugging` for the investigation discipline. Structural cleanups\nbelong to the `refactoring` skill — do them in the REFACTOR step with the\ntests green.\n\n## Final rule\n\n```\nProduction code → a test exists and failed first\nOtherwise → not TDD\n```\n\n## Provenance\n\nAdapted from `obra\u002Fsuperpowers` (MIT), © 2025 Jesse Vincent. See\n`THIRD_PARTY_NOTICES.md`.\n","# Test-Driven Development (TDD)\n\n## What I do\n\n- Enforce write-test-first: no production code without a failing test\n- Drive the RED → GREEN → REFACTOR cycle with verification at each step\n- Keep tests honest (see `references\u002Fwriting-good-tests.md`)\n\n## When to use me\n\n**Always:** new features, bug fixes, refactoring, behavior changes.\n\n**Exceptions (ask the user):** generated code, configuration files, throwaway\nprototypes. Visual\u002FUI work is not exempt by default — ask the user, and a\nPlaywright or screenshot regression check may substitute for a unit test.\n\nThinking \"skip TDD just this once\"? Stop — that is rationalization.\n\n## The Iron Law\n\n```\nNO PRODUCTION CODE WITHOUT A FAILING TEST FIRST\n```\n\nWrote code before the test — **code you wrote in this session and have not\ncommitted**? Delete it and start over: do not keep it as \"reference\", do not\nadapt it, do not look at it. Implement fresh from tests. Never delete\npre-existing, committed, or user-authored code; if the situation is unclear,\nask the user before removing anything.\n\n## The cycle\n\n1. **RED** — write one minimal test showing what should happen.\n2. **Verify RED** — run it and watch it fail for the expected reason (feature\n   missing, not a typo). A test that passes immediately is testing existing\n   behavior; fix the test.\n3. **GREEN** — write the simplest code that passes. No extra features, no refactoring beyond the test.\n4. **Verify GREEN** — run it; the new test passes and the project's suite stays\n   green. Run the project's own test command, not just your file, and report any\n   failure by name.\n5. **REFACTOR** — remove duplication, improve names, extract helpers; stay green; add no behavior.\n6. **Repeat** — next failing test for the next feature.\n\nCommits are a separate concern: follow the repository's review\u002Fcommit gate\nrather than committing once per cycle.\n\n### Good RED — clear name, real behavior, one thing\n\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```\n\n### Bad RED — vague name, tests the mock instead of the code\n\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```\n\n### Good GREEN — just enough to pass\n\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```\n\n### Bad GREEN — over-engineered beyond the test\n\n```typescript\nasync function retryOperation\u003CT>(\n  fn: () => Promise\u003CT>,\n  options?: { maxRetries?: number; backoff?: 'linear' | 'exponential'; onRetry?: (n: number) => void }\n): Promise\u003CT> { \u002F* YAGNI *\u002F }\n```\n\n## Good tests\n\n| Quality | Good | Bad |\n|---------|------|-----|\n| Minimal | One thing; \"and\" in the name → split it | `test('validates email and domain and whitespace')` |\n| Clear | Name describes the behavior | `test('test1')` |\n| Shows intent | Demonstrates the desired API | Obscures what the code should do |\n\nWhen writing or changing any test, read `references\u002Fwriting-good-tests.md`:\nname the break the test catches, derive expectations by hand, assert real\nbehavior (never the mock), and keep test-only code in test utilities.\n\n## Red flags — stop and start over\n\n- Code written before the test\n- Test passes immediately\n- Cannot explain why the test failed\n- \"I'll add tests later\" \u002F \"I already manually tested it\"\n- \"Keep as reference\" or \"adapt existing code\"\n- \"TDD is dogmatic, I'm being pragmatic\"\n\n## Common rationalizations\n\n| Excuse | Reality |\n|--------|---------|\n| \"Too simple to test\" | Simple code breaks; the test takes 30 seconds. |\n| \"I'll test after\" | Tests written after pass immediately — which proves nothing. |\n| \"Tests after achieve the same goal\" | Tests-after ask \"what does this do?\"; tests-first ask \"what should this do?\" |\n| \"Already manually tested\" | Manual testing is ad-hoc: no record, no re-run, easy to miss cases. |\n| \"Deleting hours of work is wasteful\" | Sunk cost — keeping code you cannot trust is the real waste. |\n| \"TDD slows me down\" | TDD catches bugs before commit and lets you refactor without fear. |\n\n## When stuck\n\n| Problem | Solution |\n|---------|----------|\n| Do not know how to test | Write the wished-for API; write the assertion first; ask the user. |\n| Test too complicated | The design is too complicated — simplify the interface. |\n| Must mock everything | The code is too coupled — use dependency injection. |\n\n## Debugging integration\n\nFound a bug? Write a failing test that reproduces it first, then follow the\ncycle — the test proves the fix and prevents regression. Security findings need\na regression test too: reproduce the flaw as a failing test before fixing it.\nSee `systematic-debugging` for the investigation discipline. Structural cleanups\nbelong to the `refactoring` skill — do them in the REFACTOR step with the\ntests green.\n\n## Final rule\n\n```\nProduction code → a test exists and failed first\nOtherwise → not TDD\n```\n\n## Provenance\n\nAdapted from `obra\u002Fsuperpowers` (MIT), © 2025 Jesse Vincent. See\n`THIRD_PARTY_NOTICES.md`.\n",{"name":5,"license":15,"metadata":49,"description":7,"compatibility":34},{"author":50,"version":51,"audience":52,"workflow":29},"shahboura (methodology adapted from obra\u002Fsuperpowers, MIT)","1.0.0","developers","main","9b951b5b2e5d07d427baff330db5deb2a8c67511",".opencode\u002Fskills\u002Ftest-driven-development",0,"https:\u002F\u002Fgithub.com\u002Fshahboura\u002Fagents-opencode","https:\u002F\u002Fagnts.elkodr.com\u002F","https:\u002F\u002Fgithub.com\u002Fshahboura","2026-11-05 13:30:42",{"source":8,"skillName":5,"commands":62,"prompt":72,"zipAvailable":73},[63,66,69],{"tool":64,"command":65},"npx","npx skills add shahboura\u002Fagents-opencode --skill test-driven-development",{"tool":67,"command":68},"bunx","bunx skills add shahboura\u002Fagents-opencode --skill test-driven-development",{"tool":70,"command":71},"pnpm","pnpm dlx skills add shahboura\u002Fagents-opencode --skill test-driven-development","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fshahboura\u002Fagents-opencode\u002Fblob\u002Fmain\u002F.opencode\u002Fskills\u002Ftest-driven-development\u002FSKILL.md",true,[75],{"path":76,"resourceType":77,"resourceTypeDesc":78,"sizeBytes":79,"sourceHtmlUrl":80},"references\u002Fwriting-good-tests.md","REFERENCE","参考文档",7679,"https:\u002F\u002Fgithub.com\u002Fshahboura\u002Fagents-opencode\u002Fblob\u002Fmain\u002F.opencode\u002Fskills\u002Ftest-driven-development\u002Freferences\u002Fwriting-good-tests.md",[82,88,97,102,107,112],{"skillNo":83,"name":84,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":85,"categories":86,"keywords":87,"publishedAt":44},"01M6CBBX1C6NV7VY8XK21DV5FW","python","https:\u002F\u002Fgithub.com\u002Fshahboura\u002Fagents-opencode\u002Fblob\u002Fmain\u002Fscripts\u002Ffixtures\u002Fvalidate-agents\u002Fvalid\u002F.opencode\u002Fskills\u002Fpython\u002FSKILL.md",[],[84],{"skillNo":89,"name":90,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":91,"categories":92,"keywords":93,"publishedAt":44},"01M6CBBVB7W6ABJH8XP3Z8PPMK","docs-validation","https:\u002F\u002Fgithub.com\u002Fshahboura\u002Fagents-opencode\u002Fblob\u002Fmain\u002Fscripts\u002Ffixtures\u002Fvalidate-agents\u002Fvalid\u002F.opencode\u002Fskills\u002Fdocs-validation\u002FSKILL.md",[],[94,95,96],"docs","validation","docs validation",{"skillNo":98,"name":84,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":99,"categories":100,"keywords":101,"publishedAt":44},"01M6CBBT2WC781609MH5RN7KM7","https:\u002F\u002Fgithub.com\u002Fshahboura\u002Fagents-opencode\u002Fblob\u002Fmain\u002Fscripts\u002Ffixtures\u002Fvalidate-agents\u002Funknown-skill\u002F.opencode\u002Fskills\u002Fpython\u002FSKILL.md",[],[84],{"skillNo":103,"name":90,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":104,"categories":105,"keywords":106,"publishedAt":44},"01M6CBBRNY6TDRZ5627GC8436D","https:\u002F\u002Fgithub.com\u002Fshahboura\u002Fagents-opencode\u002Fblob\u002Fmain\u002Fscripts\u002Ffixtures\u002Fvalidate-agents\u002Funknown-skill\u002F.opencode\u002Fskills\u002Fdocs-validation\u002FSKILL.md",[],[94,95,96],{"skillNo":108,"name":84,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":109,"categories":110,"keywords":111,"publishedAt":44},"01M6CBBQDS170GBYA1CVW3DC5D","https:\u002F\u002Fgithub.com\u002Fshahboura\u002Fagents-opencode\u002Fblob\u002Fmain\u002Fscripts\u002Ffixtures\u002Fvalidate-agents\u002Finline-skill\u002F.opencode\u002Fskills\u002Fpython\u002FSKILL.md",[],[84],{"skillNo":113,"name":90,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":114,"categories":115,"keywords":116,"publishedAt":44},"01M6CBBP222WAW802YHY37F48A","https:\u002F\u002Fgithub.com\u002Fshahboura\u002Fagents-opencode\u002Fblob\u002Fmain\u002Fscripts\u002Ffixtures\u002Fvalidate-agents\u002Finline-skill\u002F.opencode\u002Fskills\u002Fdocs-validation\u002FSKILL.md",[],[94,95,96]]