[{"data":1,"prerenderedAt":1383},["ShallowReactive",2],{"navigation_docs":3,"-skills-dev-skills-drill-tdd":246,"-skills-dev-skills-drill-tdd-surround":1378},[4,28,62,94,207,236,240],{"title":5,"path":6,"stem":7,"children":8,"order":11,"icon":27},"Getting Started","/getting-started","1.getting-started/index",[9,12,17,22],{"title":10,"path":6,"stem":7,"order":11},"What is Gangsta Agents?",1,{"title":13,"path":14,"stem":15,"order":16},"Installation","/getting-started/installation","1.getting-started/installation",2,{"title":18,"path":19,"stem":20,"order":21},"Quickstart — Your First Heist","/getting-started/quickstart","1.getting-started/quickstart",3,{"title":23,"path":24,"stem":25,"order":26},"The 1% Rule","/getting-started/the-1-percent-rule","1.getting-started/the-1-percent-rule",4,"i-lucide-rocket",{"title":29,"path":30,"stem":31,"children":32,"order":11,"icon":61},"Core Concepts","/core-concepts","2.core-concepts/index",[33,34,39,43,48,52,56],{"title":29,"path":30,"stem":31,"order":11},{"title":35,"path":36,"stem":37,"order":38},"Intent Routing","/core-concepts/intent-routing","2.core-concepts/intent-routing",5,{"title":40,"path":41,"stem":42,"order":26},"Omerta — The Five Laws","/core-concepts/omerta","2.core-concepts/omerta",{"title":44,"path":45,"stem":46,"order":47},"Spec-Driven Development","/core-concepts/spec-driven-dev","2.core-concepts/spec-driven-dev",7,{"title":49,"path":50,"stem":51,"order":16},"The Gangsta Agents Family Hierarchy","/core-concepts/the-borgata","2.core-concepts/the-borgata",{"title":53,"path":54,"stem":55,"order":21},"The Heist Pipeline","/core-concepts/the-heist","2.core-concepts/the-heist",{"title":57,"path":58,"stem":59,"order":60},"The Ledger","/core-concepts/the-ledger","2.core-concepts/the-ledger",6,"i-lucide-brain",{"title":63,"icon":64,"path":65,"stem":66,"children":67},"Heist Pipeline","i-lucide-workflow","/heist-pipeline","3.heist-pipeline",[68,70,74,78,82,86,90],{"title":53,"path":65,"stem":69,"order":11},"3.heist-pipeline/index",{"title":71,"path":72,"stem":73,"order":16},"Reconnaissance","/heist-pipeline/reconnaissance","3.heist-pipeline/1.reconnaissance",{"title":75,"path":76,"stem":77,"order":21},"The Grilling","/heist-pipeline/the-grilling","3.heist-pipeline/2.the-grilling",{"title":79,"path":80,"stem":81,"order":26},"The Sit-Down","/heist-pipeline/the-sit-down","3.heist-pipeline/3.the-sit-down",{"title":83,"path":84,"stem":85,"order":38},"Resource Development","/heist-pipeline/resource-development","3.heist-pipeline/4.resource-development",{"title":87,"path":88,"stem":89,"order":60},"Execution","/heist-pipeline/the-hit","3.heist-pipeline/5.the-hit",{"title":91,"path":92,"stem":93,"order":47},"The Delivery","/heist-pipeline/laundering","3.heist-pipeline/6.laundering",{"title":95,"icon":96,"path":97,"stem":98,"children":99},"Skills Reference","i-heroicons-bolt","/skills","4.skills",[100,102,138,173],{"title":95,"path":97,"stem":101,"order":11,"icon":96},"4.skills/index",{"title":103,"icon":104,"path":105,"stem":106,"children":107,"page":137},"Dev Skills","i-heroicons-wrench-screwdriver","/skills/dev-skills","4.skills/dev-skills",[108,113,117,121,125,129,133],{"title":109,"path":110,"stem":111,"order":112,"icon":96},"audit-review","/skills/dev-skills/audit-review","4.skills/dev-skills/audit-review",31,{"title":114,"path":115,"stem":116,"order":112,"icon":96},"drill-tdd","/skills/dev-skills/drill-tdd","4.skills/dev-skills/drill-tdd",{"title":118,"path":119,"stem":120,"order":112,"icon":96},"exit-strategy","/skills/dev-skills/exit-strategy","4.skills/dev-skills/exit-strategy",{"title":122,"path":123,"stem":124,"order":112,"icon":96},"interrogation-debugging","/skills/dev-skills/interrogation-debugging","4.skills/dev-skills/interrogation-debugging",{"title":126,"path":127,"stem":128,"order":112,"icon":96},"receiving-orders","/skills/dev-skills/receiving-orders","4.skills/dev-skills/receiving-orders",{"title":130,"path":131,"stem":132,"order":112,"icon":96},"safehouse-worktrees","/skills/dev-skills/safehouse-worktrees","4.skills/dev-skills/safehouse-worktrees",{"title":134,"path":135,"stem":136,"order":112,"icon":96},"sweep-verification","/skills/dev-skills/sweep-verification","4.skills/dev-skills/sweep-verification",false,{"title":139,"icon":140,"path":141,"stem":142,"children":143,"page":137},"Heist Phases","i-heroicons-academic-cap","/skills/heist-phases","4.skills/heist-phases",[144,149,154,158,163,168],{"title":145,"path":146,"stem":147,"order":148,"icon":96},"laundering","/skills/heist-phases/laundering","4.skills/heist-phases/laundering",21,{"title":150,"path":151,"stem":152,"order":153,"icon":96},"reconnaissance","/skills/heist-phases/reconnaissance","4.skills/heist-phases/reconnaissance",22,{"title":155,"path":156,"stem":157,"order":148,"icon":96},"resource-development","/skills/heist-phases/resource-development","4.skills/heist-phases/resource-development",{"title":159,"path":160,"stem":161,"order":162,"icon":96},"the-grilling","/skills/heist-phases/the-grilling","4.skills/heist-phases/the-grilling",23,{"title":164,"path":165,"stem":166,"order":167,"icon":96},"the-hit","/skills/heist-phases/the-hit","4.skills/heist-phases/the-hit",24,{"title":169,"path":170,"stem":171,"order":172,"icon":96},"the-sit-down","/skills/heist-phases/the-sit-down","4.skills/heist-phases/the-sit-down",26,{"title":174,"icon":175,"path":176,"stem":177,"children":178,"page":137},"Hierarchy Roles","i-heroicons-user-group","/skills/hierarchy-roles","4.skills/hierarchy-roles",[179,184,188,193,198,203],{"title":180,"path":181,"stem":182,"order":183,"icon":96},"omerta","/skills/hierarchy-roles/omerta","4.skills/hierarchy-roles/omerta",11,{"title":185,"path":186,"stem":187,"order":183,"icon":96},"the-capo","/skills/hierarchy-roles/the-capo","4.skills/hierarchy-roles/the-capo",{"title":189,"path":190,"stem":191,"order":192,"icon":96},"the-consigliere","/skills/hierarchy-roles/the-consigliere","4.skills/hierarchy-roles/the-consigliere",12,{"title":194,"path":195,"stem":196,"order":197,"icon":96},"the-ledger","/skills/hierarchy-roles/the-ledger","4.skills/hierarchy-roles/the-ledger",15,{"title":199,"path":200,"stem":201,"order":202,"icon":96},"the-underboss","/skills/hierarchy-roles/the-underboss","4.skills/hierarchy-roles/the-underboss",17,{"title":204,"path":205,"stem":206,"order":183,"icon":96},"using-gangsta","/skills/hierarchy-roles/using-gangsta","4.skills/hierarchy-roles/using-gangsta",{"title":208,"icon":209,"path":210,"stem":211,"children":212},"Advanced","i-lucide-zap","/advanced","5.advanced",[213,216,220,224,228,232],{"title":214,"path":210,"stem":215,"order":11},"Advanced Topics","5.advanced/index",{"title":217,"path":218,"stem":219,"order":38},"Artifacts Reference","/advanced/artifacts","5.advanced/artifacts",{"title":221,"path":222,"stem":223,"order":26},"Checkpoint Recovery","/advanced/checkpoint-recovery","5.advanced/checkpoint-recovery",{"title":225,"path":226,"stem":227,"order":38},"Contributing","/advanced/contributing","5.advanced/contributing",{"title":229,"path":230,"stem":231,"order":16},"Writing Custom Skills","/advanced/custom-skills","5.advanced/custom-skills",{"title":233,"path":234,"stem":235,"order":21},"Multi-Agent Patterns","/advanced/multi-agent-patterns","5.advanced/multi-agent-patterns",{"title":237,"path":238,"stem":239,"order":60},"Glossary","/glossary","6.glossary",{"title":241,"path":242,"stem":243,"order":244,"icon":245},"Changelog","/changelog","7.changelog",8,"i-lucide-scroll-text",{"id":247,"title":114,"body":248,"description":1371,"extension":1372,"links":1373,"meta":1374,"navigation":1375,"path":115,"seo":1376,"stem":116,"__hash__":1377},"docs/4.skills/dev-skills/drill-tdd.md",{"type":249,"value":250,"toc":1349},"minimark",[251,256,261,265,272,277,281,286,302,307,318,321,325,336,339,344,358,361,365,477,482,485,1345],[252,253,255],"h1",{"id":254},"the-drill-test-driven-development","The Drill: Test-Driven Development",[257,258,260],"h2",{"id":259},"overview","Overview",[262,263,264],"p",{},"Write the test first. Watch it fail. Write minimal code to pass.",[262,266,267,271],{},[268,269,270],"strong",{},"Core principle:"," If you didn't watch the test fail, you don't know if it tests the right thing.",[262,273,274],{},[268,275,276],{},"Violating the letter of the rules is violating the spirit of the rules.",[257,278,280],{"id":279},"when-to-use","When to Use",[262,282,283],{},[268,284,285],{},"Always:",[287,288,289,293,296,299],"ul",{},[290,291,292],"li",{},"New features",[290,294,295],{},"Bug fixes",[290,297,298],{},"Refactoring",[290,300,301],{},"Behavior changes",[262,303,304],{},[268,305,306],{},"Exceptions (ask the Don):",[287,308,309,312,315],{},[290,310,311],{},"Throwaway prototypes",[290,313,314],{},"Generated code",[290,316,317],{},"Configuration files",[262,319,320],{},"Thinking \"skip the Drill just this once\"? Stop. That's rationalization.",[257,322,324],{"id":323},"the-iron-law-the-omerta-of-testing","The Iron Law (The Omerta of Testing)",[326,327,332],"pre",{"className":328,"code":330,"language":331},[329],"language-text","NO PRODUCTION CODE WITHOUT A FAILING TEST FIRST\n","text",[333,334,330],"code",{"__ignoreMap":335},"",[262,337,338],{},"Write code before the test? Delete it. Start over.",[262,340,341],{},[268,342,343],{},"No exceptions:",[287,345,346,349,352,355],{},[290,347,348],{},"Don't keep it as \"reference\"",[290,350,351],{},"Don't \"adapt\" it while writing tests",[290,353,354],{},"Don't look at it",[290,356,357],{},"Delete means delete",[262,359,360],{},"Implement fresh from tests. Period.",[257,362,364],{"id":363},"red-green-refactor","Red-Green-Refactor",[326,366,370],{"className":367,"code":368,"language":369,"meta":335,"style":335},"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",[333,371,372,379,384,389,394,399,404,409,414,421,427,432,437,443,449,454,460,465,471],{"__ignoreMap":335},[373,374,376],"span",{"class":375,"line":11},"line",[373,377,378],{},"digraph tdd_cycle {\n",[373,380,381],{"class":375,"line":16},[373,382,383],{},"    rankdir=LR;\n",[373,385,386],{"class":375,"line":21},[373,387,388],{},"    red [label=\"RED\\nWrite failing test\", shape=box, style=filled, fillcolor=\"#ffcccc\"];\n",[373,390,391],{"class":375,"line":26},[373,392,393],{},"    verify_red [label=\"Verify fails\\ncorrectly\", shape=diamond];\n",[373,395,396],{"class":375,"line":38},[373,397,398],{},"    green [label=\"GREEN\\nMinimal code\", shape=box, style=filled, fillcolor=\"#ccffcc\"];\n",[373,400,401],{"class":375,"line":60},[373,402,403],{},"    verify_green [label=\"Verify passes\\nAll green\", shape=diamond];\n",[373,405,406],{"class":375,"line":47},[373,407,408],{},"    refactor [label=\"REFACTOR\\nClean up\", shape=box, style=filled, fillcolor=\"#ccccff\"];\n",[373,410,411],{"class":375,"line":244},[373,412,413],{},"    next [label=\"Next\", shape=ellipse];\n",[373,415,417],{"class":375,"line":416},9,[373,418,420],{"emptyLinePlaceholder":419},true,"\n",[373,422,424],{"class":375,"line":423},10,[373,425,426],{},"    red -> verify_red;\n",[373,428,429],{"class":375,"line":183},[373,430,431],{},"    verify_red -> green [label=\"yes\"];\n",[373,433,434],{"class":375,"line":192},[373,435,436],{},"    verify_red -> red [label=\"wrong\\nfailure\"];\n",[373,438,440],{"class":375,"line":439},13,[373,441,442],{},"    green -> verify_green;\n",[373,444,446],{"class":375,"line":445},14,[373,447,448],{},"    verify_green -> refactor [label=\"yes\"];\n",[373,450,451],{"class":375,"line":197},[373,452,453],{},"    verify_green -> green [label=\"no\"];\n",[373,455,457],{"class":375,"line":456},16,[373,458,459],{},"    refactor -> verify_green [label=\"stay\\ngreen\"];\n",[373,461,462],{"class":375,"line":202},[373,463,464],{},"    verify_green -> next;\n",[373,466,468],{"class":375,"line":467},18,[373,469,470],{},"    next -> red;\n",[373,472,474],{"class":375,"line":473},19,[373,475,476],{},"}\n",[478,479,481],"h3",{"id":480},"red-write-failing-test","RED — Write Failing Test",[262,483,484],{},"Write one minimal test showing what should happen.",[486,487,488,489,492,495,501,504,509,520,524,529,532,543,549,555,559,562,575,587,590,594,599,601,612,618,624,628,631,642,645,649,652,656,722,726,731,734,748,751,756,759,767,770,775,778,792,795,799,885,889,918,923,927,933,938,1068,1073,1079,1084,1180,1185,1191,1197,1201,1204,1259,1262,1266,1269,1276,1280,1326,1330],"good",{},"\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",[262,490,491],{},"const result = await retryOperation(operation);",[262,493,494],{},"expect(result).toBe('success');\nexpect(attempts).toBe(3);\n});",[326,496,499],{"className":497,"code":498,"language":331},[329],"Clear name, tests real behavior, one thing\n\u003C/Good>\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",[333,500,498],{"__ignoreMap":335},[262,502,503],{},"Vague name, tests mock not code\n",[262,505,506],{},[268,507,508],{},"Requirements:",[287,510,511,514,517],{},[290,512,513],{},"One behavior per test",[290,515,516],{},"Clear descriptive name",[290,518,519],{},"Real code (no mocks unless unavoidable)",[478,521,523],{"id":522},"verify-red-watch-it-fail","Verify RED — Watch It Fail",[262,525,526],{},[268,527,528],{},"MANDATORY. Never skip.",[262,530,531],{},"Run the test. Confirm:",[287,533,534,537,540],{},[290,535,536],{},"Test fails (not errors)",[290,538,539],{},"Failure message is expected",[290,541,542],{},"Fails because feature missing (not typos)",[262,544,545,548],{},[268,546,547],{},"Test passes?"," You're testing existing behavior. Fix the test.",[262,550,551,554],{},[268,552,553],{},"Test errors?"," Fix the error, re-run until it fails correctly.",[478,556,558],{"id":557},"green-minimal-code","GREEN — Minimal Code",[262,560,561],{},"Write the simplest code to pass the test.",[486,563,564,565],{},"\n```typescript\nasync function retryOperation",[566,567,568,569],"t",{},"(fn: () => Promise",[566,570,571,572],{},"): Promise",[566,573,574],{}," {\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",[576,577,564,578],"bad",{},[566,579,580,581],{},"(\n  fn: () => Promise",[566,582,583,584],{},",\n  options?: {\n    maxRetries?: number;\n    backoff?: 'linear' | 'exponential';\n    onRetry?: (attempt: number) => void;\n  }\n): Promise",[566,585,586],{}," {\n  // YAGNI — over-engineered\n}\n```\nOver-engineered\n",[262,588,589],{},"Don't add features, refactor other code, or \"improve\" beyond the test.",[478,591,593],{"id":592},"verify-green-watch-it-pass","Verify GREEN — Watch It Pass",[262,595,596],{},[268,597,598],{},"MANDATORY.",[262,600,531],{},[287,602,603,606,609],{},[290,604,605],{},"Test passes",[290,607,608],{},"Other tests still pass",[290,610,611],{},"Output pristine (no errors, warnings)",[262,613,614,617],{},[268,615,616],{},"Test fails?"," Fix code, not test.",[262,619,620,623],{},[268,621,622],{},"Other tests fail?"," Fix now.",[478,625,627],{"id":626},"refactor-clean-up","REFACTOR — Clean Up",[262,629,630],{},"After green only:",[287,632,633,636,639],{},[290,634,635],{},"Remove duplication",[290,637,638],{},"Improve names",[290,640,641],{},"Extract helpers",[262,643,644],{},"Keep tests green. Don't add behavior.",[478,646,648],{"id":647},"repeat","Repeat",[262,650,651],{},"Next failing test for next behavior.",[257,653,655],{"id":654},"good-tests","Good Tests",[657,658,659,675],"table",{},[660,661,662],"thead",{},[663,664,665,669,672],"tr",{},[666,667,668],"th",{},"Quality",[666,670,671],{},"Good",[666,673,674],{},"Bad",[676,677,678,694,709],"tbody",{},[663,679,680,686,689],{},[681,682,683],"td",{},[268,684,685],{},"Minimal",[681,687,688],{},"One thing. \"and\" in name? Split it.",[681,690,691],{},[333,692,693],{},"test('validates email and domain and whitespace')",[663,695,696,701,704],{},[681,697,698],{},[268,699,700],{},"Clear",[681,702,703],{},"Name describes behavior",[681,705,706],{},[333,707,708],{},"test('test1')",[663,710,711,716,719],{},[681,712,713],{},[268,714,715],{},"Shows intent",[681,717,718],{},"Demonstrates desired API",[681,720,721],{},"Obscures what code should do",[257,723,725],{"id":724},"why-order-matters","Why Order Matters",[262,727,728],{},[268,729,730],{},"\"I'll write tests after to verify it works\"",[262,732,733],{},"Tests written after code pass immediately. Passing immediately proves nothing:",[287,735,736,739,742,745],{},[290,737,738],{},"Might test wrong thing",[290,740,741],{},"Might test implementation, not behavior",[290,743,744],{},"Might miss edge cases you forgot",[290,746,747],{},"You never saw it catch the bug",[262,749,750],{},"Test-first forces you to see the test fail, proving it actually tests something.",[262,752,753],{},[268,754,755],{},"\"Deleting X hours of work is wasteful\"",[262,757,758],{},"Sunk cost fallacy. The time is already gone. Your choice now:",[287,760,761,764],{},[290,762,763],{},"Delete and rewrite with TDD (high confidence)",[290,765,766],{},"Keep it and add tests after (low confidence, likely bugs)",[262,768,769],{},"The \"waste\" is keeping code you can't trust.",[262,771,772],{},[268,773,774],{},"\"TDD is dogmatic, being pragmatic means adapting\"",[262,776,777],{},"TDD IS pragmatic:",[287,779,780,783,786,789],{},[290,781,782],{},"Finds bugs before commit (faster than debugging after)",[290,784,785],{},"Prevents regressions (tests catch breaks immediately)",[290,787,788],{},"Documents behavior (tests show how to use code)",[290,790,791],{},"Enables refactoring (change freely, tests catch breaks)",[262,793,794],{},"\"Pragmatic\" shortcuts = debugging in production = slower.",[257,796,798],{"id":797},"common-rationalizations","Common Rationalizations",[657,800,801,811],{},[660,802,803],{},[663,804,805,808],{},[666,806,807],{},"Excuse",[666,809,810],{},"Reality",[676,812,813,821,829,837,845,853,861,869,877],{},[663,814,815,818],{},[681,816,817],{},"\"Too simple to test\"",[681,819,820],{},"Simple code breaks. Test takes 30 seconds.",[663,822,823,826],{},[681,824,825],{},"\"I'll test after\"",[681,827,828],{},"Tests passing immediately prove nothing.",[663,830,831,834],{},[681,832,833],{},"\"Already manually tested\"",[681,835,836],{},"Ad-hoc ≠ systematic. No record, can't re-run.",[663,838,839,842],{},[681,840,841],{},"\"Deleting X hours is wasteful\"",[681,843,844],{},"Sunk cost fallacy. Keeping unverified code is debt.",[663,846,847,850],{},[681,848,849],{},"\"Keep as reference, write tests first\"",[681,851,852],{},"You'll adapt it. That's testing after. Delete means delete.",[663,854,855,858],{},[681,856,857],{},"\"Need to explore first\"",[681,859,860],{},"Fine. Throw away exploration, start with the Drill.",[663,862,863,866],{},[681,864,865],{},"\"Test hard = design unclear\"",[681,867,868],{},"Listen to test. Hard to test = hard to use.",[663,870,871,874],{},[681,872,873],{},"\"TDD will slow me down\"",[681,875,876],{},"The Drill is faster than debugging.",[663,878,879,882],{},[681,880,881],{},"\"Existing code has no tests\"",[681,883,884],{},"You're improving it. Add tests for what you touch.",[257,886,888],{"id":887},"red-flags-stop-and-start-over","Red Flags — STOP and Start Over",[287,890,891,894,897,900,903,906,909,912,915],{},[290,892,893],{},"Code before test",[290,895,896],{},"Test after implementation",[290,898,899],{},"Test passes immediately",[290,901,902],{},"Can't explain why test failed",[290,904,905],{},"Tests added \"later\"",[290,907,908],{},"Rationalizing \"just this once\"",[290,910,911],{},"\"Keep as reference\" or \"adapt existing code\"",[290,913,914],{},"\"Already spent X hours, deleting is wasteful\"",[290,916,917],{},"\"TDD is dogmatic, I'm being pragmatic\"",[262,919,920],{},[268,921,922],{},"All of these mean: Delete code. Start over with the Drill.",[257,924,926],{"id":925},"example-bug-fix","Example: Bug Fix",[262,928,929,932],{},[268,930,931],{},"Bug:"," Empty email accepted",[262,934,935],{},[268,936,937],{},"RED",[326,939,943],{"className":940,"code":941,"language":942,"meta":335,"style":335},"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",[333,944,945,981,1023,1059],{"__ignoreMap":335},[373,946,947,951,955,959,963,965,968,972,975,978],{"class":375,"line":11},[373,948,950],{"class":949},"s2Zo4","test",[373,952,954],{"class":953},"sTEyZ","(",[373,956,958],{"class":957},"sMK4o","'",[373,960,962],{"class":961},"sfazB","rejects empty email",[373,964,958],{"class":957},[373,966,967],{"class":957},",",[373,969,971],{"class":970},"spNyl"," async",[373,973,974],{"class":957}," ()",[373,976,977],{"class":970}," =>",[373,979,980],{"class":957}," {\n",[373,982,983,986,989,992,996,999,1002,1005,1008,1011,1014,1017,1020],{"class":375,"line":16},[373,984,985],{"class":970},"  const",[373,987,988],{"class":953}," result",[373,990,991],{"class":957}," =",[373,993,995],{"class":994},"s7zQu"," await",[373,997,998],{"class":949}," submitForm",[373,1000,954],{"class":1001},"swJcz",[373,1003,1004],{"class":957},"{",[373,1006,1007],{"class":1001}," email",[373,1009,1010],{"class":957},":",[373,1012,1013],{"class":957}," ''",[373,1015,1016],{"class":957}," }",[373,1018,1019],{"class":1001},")",[373,1021,1022],{"class":957},";\n",[373,1024,1025,1028,1030,1033,1036,1039,1041,1043,1046,1048,1050,1053,1055,1057],{"class":375,"line":21},[373,1026,1027],{"class":949},"  expect",[373,1029,954],{"class":1001},[373,1031,1032],{"class":953},"result",[373,1034,1035],{"class":957},".",[373,1037,1038],{"class":953},"error",[373,1040,1019],{"class":1001},[373,1042,1035],{"class":957},[373,1044,1045],{"class":949},"toBe",[373,1047,954],{"class":1001},[373,1049,958],{"class":957},[373,1051,1052],{"class":961},"Email required",[373,1054,958],{"class":957},[373,1056,1019],{"class":1001},[373,1058,1022],{"class":957},[373,1060,1061,1064,1066],{"class":375,"line":26},[373,1062,1063],{"class":957},"}",[373,1065,1019],{"class":953},[373,1067,1022],{"class":957},[262,1069,1070],{},[268,1071,1072],{},"Verify RED",[326,1074,1077],{"className":1075,"code":1076,"language":331},[329],"$ npm test\nFAIL: expected 'Email required', got undefined\n",[333,1078,1076],{"__ignoreMap":335},[262,1080,1081],{},[268,1082,1083],{},"GREEN",[326,1085,1087],{"className":940,"code":1086,"language":942,"meta":335,"style":335},"function submitForm(data: FormData) {\n  if (!data.email?.trim()) {\n    return { error: 'Email required' };\n  }\n  // ...existing code\n}\n",[333,1088,1089,1112,1142,1165,1170,1176],{"__ignoreMap":335},[373,1090,1091,1094,1096,1098,1102,1104,1108,1110],{"class":375,"line":11},[373,1092,1093],{"class":970},"function",[373,1095,998],{"class":949},[373,1097,954],{"class":957},[373,1099,1101],{"class":1100},"sHdIc","data",[373,1103,1010],{"class":957},[373,1105,1107],{"class":1106},"sBMFI"," FormData",[373,1109,1019],{"class":957},[373,1111,980],{"class":957},[373,1113,1114,1117,1120,1123,1125,1127,1130,1133,1136,1139],{"class":375,"line":16},[373,1115,1116],{"class":994},"  if",[373,1118,1119],{"class":1001}," (",[373,1121,1122],{"class":957},"!",[373,1124,1101],{"class":953},[373,1126,1035],{"class":957},[373,1128,1129],{"class":953},"email",[373,1131,1132],{"class":957},"?.",[373,1134,1135],{"class":949},"trim",[373,1137,1138],{"class":1001},"()) ",[373,1140,1141],{"class":957},"{\n",[373,1143,1144,1147,1150,1153,1155,1158,1160,1162],{"class":375,"line":21},[373,1145,1146],{"class":994},"    return",[373,1148,1149],{"class":957}," {",[373,1151,1152],{"class":1001}," error",[373,1154,1010],{"class":957},[373,1156,1157],{"class":957}," '",[373,1159,1052],{"class":961},[373,1161,958],{"class":957},[373,1163,1164],{"class":957}," };\n",[373,1166,1167],{"class":375,"line":26},[373,1168,1169],{"class":957},"  }\n",[373,1171,1172],{"class":375,"line":38},[373,1173,1175],{"class":1174},"sHwdD","  // ...existing code\n",[373,1177,1178],{"class":375,"line":60},[373,1179,476],{"class":957},[262,1181,1182],{},[268,1183,1184],{},"Verify GREEN",[326,1186,1189],{"className":1187,"code":1188,"language":331},[329],"$ npm test\nPASS\n",[333,1190,1188],{"__ignoreMap":335},[262,1192,1193,1196],{},[268,1194,1195],{},"REFACTOR"," — Extract validation for multiple fields if needed.",[257,1198,1200],{"id":1199},"verification-checklist","Verification Checklist",[262,1202,1203],{},"Before marking work complete:",[287,1205,1208,1217,1223,1229,1235,1241,1247,1253],{"className":1206},[1207],"contains-task-list",[290,1209,1212,1216],{"className":1210},[1211],"task-list-item",[1213,1214],"input",{"disabled":419,"type":1215},"checkbox"," Every new function/method has a test",[290,1218,1220,1222],{"className":1219},[1211],[1213,1221],{"disabled":419,"type":1215}," Watched each test fail before implementing",[290,1224,1226,1228],{"className":1225},[1211],[1213,1227],{"disabled":419,"type":1215}," Each test failed for expected reason (feature missing, not typo)",[290,1230,1232,1234],{"className":1231},[1211],[1213,1233],{"disabled":419,"type":1215}," Wrote minimal code to pass each test",[290,1236,1238,1240],{"className":1237},[1211],[1213,1239],{"disabled":419,"type":1215}," All tests pass",[290,1242,1244,1246],{"className":1243},[1211],[1213,1245],{"disabled":419,"type":1215}," Output pristine (no errors, warnings)",[290,1248,1250,1252],{"className":1249},[1211],[1213,1251],{"disabled":419,"type":1215}," Tests use real code (mocks only if unavoidable)",[290,1254,1256,1258],{"className":1255},[1211],[1213,1257],{"disabled":419,"type":1215}," Edge cases and errors covered",[262,1260,1261],{},"Can't check all boxes? You skipped the Drill. Start over.",[257,1263,1265],{"id":1264},"debugging-integration","Debugging Integration",[262,1267,1268],{},"Bug found? Write failing test reproducing it. Follow the Drill cycle. Test proves fix and prevents regression.",[262,1270,1271,1272,1275],{},"Never fix bugs without a test. Use ",[333,1273,1274],{},"gangsta:interrogation-debugging"," for root-cause investigation first.",[257,1277,1279],{"id":1278},"when-stuck","When Stuck",[657,1281,1282,1292],{},[660,1283,1284],{},[663,1285,1286,1289],{},[666,1287,1288],{},"Problem",[666,1290,1291],{},"Solution",[676,1293,1294,1302,1310,1318],{},[663,1295,1296,1299],{},[681,1297,1298],{},"Don't know how to test",[681,1300,1301],{},"Write wished-for API. Write assertion first. Ask the Don.",[663,1303,1304,1307],{},[681,1305,1306],{},"Test too complicated",[681,1308,1309],{},"Design too complicated. Simplify interface.",[663,1311,1312,1315],{},[681,1313,1314],{},"Must mock everything",[681,1316,1317],{},"Code too coupled. Use dependency injection.",[663,1319,1320,1323],{},[681,1321,1322],{},"Test setup huge",[681,1324,1325],{},"Extract helpers. Still complex? Simplify design.",[257,1327,1329],{"id":1328},"omerta-compliance","Omerta Compliance",[287,1331,1333,1339],{"className":1332},[1207],[290,1334,1336,1338],{"className":1335},[1211],[1213,1337],{"disabled":419,"type":1215}," Rule of Truth: Test output is actual command output, not claims",[290,1340,1342,1344],{"className":1341},[1211],[1213,1343],{"disabled":419,"type":1215}," Spec is Law: Every implementation traces to a test that traces to a requirement",[1346,1347,1348],"style",{},"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);}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}",{"title":335,"searchDepth":16,"depth":16,"links":1350},[1351,1352,1353,1354,1362,1363,1364,1365,1366,1367,1368,1369,1370],{"id":259,"depth":16,"text":260},{"id":279,"depth":16,"text":280},{"id":323,"depth":16,"text":324},{"id":363,"depth":16,"text":364,"children":1355},[1356,1357,1358,1359,1360,1361],{"id":480,"depth":21,"text":481},{"id":522,"depth":21,"text":523},{"id":557,"depth":21,"text":558},{"id":592,"depth":21,"text":593},{"id":626,"depth":21,"text":627},{"id":647,"depth":21,"text":648},{"id":654,"depth":16,"text":655},{"id":724,"depth":16,"text":725},{"id":797,"depth":16,"text":798},{"id":887,"depth":16,"text":888},{"id":925,"depth":16,"text":926},{"id":1199,"depth":16,"text":1200},{"id":1264,"depth":16,"text":1265},{"id":1278,"depth":16,"text":1279},{"id":1328,"depth":16,"text":1329},"Use when implementing any feature or bugfix — enforces the Red-Green-Refactor drill with no production code allowed without a failing test first","md",null,{"name":114},{"order":112,"icon":96},{"title":114,"description":1371},"9JUDv6ocjlwHPfAT1-AMJLZeKuXHFQ75cZ5hsopXPVw",[1379,1381],{"title":109,"path":110,"stem":111,"description":1380,"order":112,"icon":96,"children":-1},"Use when completing tasks, implementing major features, or before merging — dispatches the-inspector to audit the books before the job is closed",{"title":118,"path":119,"stem":120,"description":1382,"order":112,"icon":96,"children":-1},"Use when implementation is complete and all tests pass — guides the clean exit from a development branch with structured options for merge, PR, or cleanup",1793043438546]