[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"blog-site-config":3,"$fb7pOqHh2yIKAHqOhPBg4hQPlp9oVhj6SW3L-qPJorqQ":6,"mdc-59g12f-key":84},{"gaMeasurementId":4,"bookingUrl":5},"G-7BYTDCVDDR","https:\u002F\u002Ftidycal.com\u002Fcmdcntr\u002F30-minute-meeting",{"post":7,"related":69},{"id":8,"slug":9,"title":10,"description":11,"summary":12,"content":13,"coverImageUrl":14,"coverImageAlt":15,"tags":16,"targetKeywords":22,"faq":23,"howTo":12,"demo":12,"featured":36,"tool":12,"status":37,"reviewNote":12,"metaTitle":38,"metaDescription":39,"canonicalUrl":40,"sourceTicketId":12,"agentGenerated":36,"publishedAt":41,"publishedBy":42,"createdAt":43,"updatedAt":41,"authorId":44,"clusterId":45,"ctaId":46,"author":47,"cluster":58,"cta":62,"tools":68},"15c5cc69-3d6b-455e-860c-ed71f11cfa73","qa-is-part-of-the-build","QA Is Part of the Build: Where Testing Belongs in Your Definition of Done","A demo failed because a shared environment was left in an unknown state. The lesson: QA is not a handoff. It belongs in the engineer's definition of done, at every company size.",null,"**The short answer.** Quality assurance is not a checkpoint at the end that someone else owns. It is part of the engineer's definition of done, and it starts with proving the software works for the people and paths that carry most of the real traffic. How much proof you need depends on the size of the company and what a bug costs. Who owns the answer never changes.\n\n## The demo that didn't happen\n\nWhen I came back from leave, I joined a customer meeting expecting to walk through part of a platform my team had been building. Instead, the shared development environment was unusable for the demo. The account shown as the administrator had the wrong email address on it. The tenant switcher wasn't reliable enough to reach the tenant we needed.\n\nThe email mismatch wasn't an accident. A developer had put their own address on the administrator account to test email notifications and hadn't put the shared data back. The feature had been exercised through the admin account, even though standard users are the people most likely to subscribe to those notifications in real use.\n\nNone of this was catastrophic. It was development, not production, and the immediate problem got fixed. That's exactly why it was worth talking about. Development is where we build the habits that eventually reach production.\n\nThe useful question wasn't \"did the notification send?\" It was \"did we prove the feature works the way our users are most likely to use it?\"\n\nI want to be fair to the developer here. They took the feedback well and agreed to test the other roles. The conversation was about the pattern, not the person. I've caused production incidents of my own. That is the reason I care about building this habit early, while the blast radius is still small.\n\n## Did we test the feature, or did we test the user's path?\n\nTesting a feature is not the same as testing user behavior.\n\nAn administrator account is often the fastest route to a screen or a permission. If administrators aren't the primary users of the feature, a green admin test proves an edge path. It says nothing about the dominant one. Permissions, tenant context, seed data, navigation, and account state can all hide behind a passing result.\n\nThis is the mentality I want engineers to carry:\n\n> Don't ask only whether the code can work. Ask whether we have evidence that it works for the user, role, data, and environment that will carry most of the real traffic.\n\nFor the notification feature, that means seeding a standard user, subscribing as that user, triggering the notification, and confirming the outcome from that user's side of the screen. The admin test is extra coverage. It isn't the main proof.\n\n## What \"QA is part of the build\" means in practice\n\nFive habits. None of them require a QA department.\n\n### Start with the dominant user journey\n\nFigure out who uses the feature most and test that path first. Secondary roles and edge cases still matter. They extend coverage. They don't substitute for the primary journey.\n\n### Treat a shared dev environment like a product when people depend on it\n\n\"It's only dev\" is a fair statement about blast radius. It's not a reason to leave the environment in an unknown state. If customers, product owners, or other developers use it for demos and acceptance, it has an operational purpose. Until a production environment exists, dev may be the most visible version of the product there is. Its reliability affects trust even when no production data is at risk.\n\n### Cleanup is part of the test\n\nA test that mutates shared data isn't finished when the assertion passes. It's finished when the environment is restored or the temporary data is isolated. Prefer disposable test users and repeatable seed data over editing shared identities. When temporary data is unavoidable, put the cleanup in the same change or the same workflow. A cleanup pull request should be the exception, not the mechanism.\n\n### A passing check is not the same as enough evidence\n\nOne passing scenario answers one narrow question. Engineering judgment is deciding whether that question is representative enough to support release confidence. Before you call something done, run through this:\n\n- Who is the primary user?\n- What is their most common path?\n- Which permissions, tenant state, and data does that path depend on?\n- What did this test actually prove?\n- What could still fail even though it passed?\n- Did the test leave shared state clean and predictable?\n\n![The six-question pre-release check laid out as a numbered checklist in two columns. One: who is the primary user, meaning the role that carries most of the real traffic, not the fastest account to reach the screen. Two: what is their most common path, which gets tested first while secondary roles and edge cases extend coverage rather than replace it. Three: which permissions, tenant state, and data does that path depend on, since all of them can hide behind a green result. Four: what did this test actually prove, because an admin test of a feature built for standard users proves an edge path. Five: what could still fail even though it passed, naming the residual risk before release. Six: did the test leave shared state clean and predictable, because a test that mutates shared data is finished when the environment is restored, not when the assertion passes.](\u002Fcovers\u002Fai-best-practices\u002Fvisuals\u002Fqa-pre-release-check.webp)\n\n### Engineers own quality even when a QA role exists\n\nDedicated QA people bring independence and exploratory thinking the builder doesn't have. Their involvement doesn't move ownership. The person who implemented the change is responsible for understanding its behavior, testing the expected paths, and handing over evidence that it's ready for broader validation. QA deepens and challenges that evidence. It should never be the first time anyone asks whether the feature works the way a real user would use it.\n\n## Why is it important to establish a definition of done?\n\nA definition of done is the shared checklist a change has to clear before the team calls it finished. It matters because without one, \"done\" means whatever the last person to touch the work decided it meant. Putting QA inside that definition is what stops testing from turning into a handoff.\n\nMost teams already have some version of this. Code written, reviewed, merged. The gap I see over and over is that \"tested\" sits in the list as a single word and nobody has agreed on what it means. Tested by whom? As which user? With what data? In which environment, and was that environment left the way you found it?\n\nIf your definition of done doesn't answer those questions, your QA is a vibe. Add the six questions above and you've turned a word into a standard. That's the whole change.\n\nOne distinction worth keeping straight: acceptance criteria describe what one feature has to do. The definition of done describes what every change has to clear. QA belongs in the second one, so it applies whether or not anyone remembered to write a test case into the ticket.\n\n## AI raises the cost of a weak quality mentality\n\nAI can produce code faster than a team can understand and validate it. If engineers treat generated code as finished code, output goes up and confidence goes down. The bottleneck moves from writing syntax to exercising judgment: picking representative scenarios, noticing the missing case, questioning assumptions, and deciding what evidence is enough.\n\nWe've written about what this looks like when the missing case is [a security boundary in AI-generated authentication](\u002Fblog\u002Ffix-ai-code\u002Fwhy-ai-generated-authentication-breaks) or [an accessibility affordance in a generated UI component](\u002Fblog\u002Fai-best-practices\u002Fai-generated-ui-components-fail-wcag-2-2-review-checklist). It's the same pattern as the admin account. The tool optimized for the path in front of it. The path in front of it was not the path most users take.\n\nThe more implementation we hand to AI, the more deliberately humans have to own validation. AI changes how code gets produced. It doesn't change who is accountable for the result. If you're moving a vibe-coded app toward real users, [the migration playbook](\u002Fblog\u002Fvibe-coding\u002Fvibe-code-to-production-migration-playbook) walks through where that scrutiny goes first.\n\n## QA strategy by company stage: enterprise, SMB, and startup\n\n![Three cards comparing QA strategy by company stage. Enterprise and large SaaS: a bug costs contracts, renewals, and reputation at scale, so QA is heavy with regression suites, staging that mirrors production, release gates, and sign-offs, and speed comes from parallel teams and automation rather than the release process. Mature SMB: a bug costs a lost order, a support ticket, or a client's confidence, so QA is balanced with full coverage on revenue paths and lighter elsewhere, and speed comes from client review in staging, small batches, and fast fixes. Startup or personal project: a bug costs a day of a founder's time and occasionally a user, so QA is light with the dominant path proven and everything else watched, and speed comes from shipping first, fixing in hours, and talking to users. Footer: the tiers change how much you test, not whether you own the answer.](\u002Fcovers\u002Fai-best-practices\u002Fvisuals\u002Fqa-strategy-by-company-stage.webp)\n\nHow much QA you need is a function of what a bug costs and who absorbs it. Enterprise and large software-as-a-service (SaaS) companies front-load quality because the software is the product, so they accept slower delivery. A mature small or mid-sized business (SMB) balances the two. A startup or side project leans on speed and uses a fast customer feedback loop as part of its QA. Every tier still owns the answer to \"what did we prove?\"\n\nI've shipped code at billion-dollar companies and for two-person startups. The QA mentality is the same at both. The amount of process wrapped around it is not, and pretending otherwise is how teams either drown in ceremony or ship checkout bugs.\n\n| Tier | What a bug costs | How much QA | Where the speed comes from |\n|---|---|---|---|\n| Enterprise \u002F large SaaS | Contracts, renewals, reputation at scale | Heavy. Regression suites, staging that mirrors production, release gates, sign-offs | Not from the release process. From parallel teams and automation |\n| Mature SMB | A lost order, a support ticket, a client's confidence | Balanced. Full coverage on revenue paths, lighter everywhere else | Client review in staging, small batches, fast fixes |\n| Startup \u002F personal project | A day of a founder's time, occasionally a user | Light. Dominant path proven, everything else watched | Shipping first, fixing in hours, talking to users |\n\n### Enterprise and large SaaS: satisfaction is the product\n\nWhen the software is the entire product, satisfaction with the software is the entire business. Every renewal depends on it. So the process front-loads quality. Regression suites that take hours. Staging environments that mirror production. Release trains. Sign-offs from people who never touched the code. A small fix can take weeks to reach a customer.\n\nThat slowness isn't incompetence. It's a decision that a bug at scale costs more than waiting does. AI doesn't change that math. It makes more code arrive at the gate. It doesn't make the gate cheaper, because the gate exists to catch what the author didn't think of, and the author is now sometimes a model.\n\nHow customers are treated at this tier: they should never be the ones finding the bug. Communication is formal and scheduled. Status pages, release notes, an account manager who calls before you notice.\n\nThe detriment shows up when process built for the big release gets applied to the one-line fix. Engineers stop testing with intent because \"QA will catch it.\" That is the failure mode from the demo story in miniature, and it happens at every company size.\n\n### Mature SMB: balance, and be honest about which paths matter\n\nThis is most of our clients at Command Center. Real revenue moves through the site. There's no QA department, and there never will be one. So the strategy is to sort paths by what they cost when they break.\n\nRevenue paths get the enterprise treatment. Checkout, lead forms, login, anything that sends an email a customer is waiting on. Those get tested as the actual user, with realistic data, in staging. The client sees it working before it goes live. Our staging, review, then live workflow exists because of this tier. The client reviewing in staging is a QA step, and it's the one that catches the \"that's not how our customers use it\" bug an engineer can't see from inside the code.\n\nEverything else gets a lighter pass, and we say so. A layout glitch on a page that gets thirty visits a month can ship. The client hears \"we tested the checkout end to end on desktop and mobile; we did not test the archive page on every phone.\" That sentence is the difference between a client who trusts you and one who feels ambushed.\n\nHere's the shape of a typical week. A client asks for a change to how shipping gets calculated. We build it in staging, run three real orders through as a customer would (not as the store admin), and send the client a short screen recording plus a note listing what we tried. They place a test order themselves. It goes live the next morning. Two days later they report that a specific coupon combination shows the wrong total. We had said coupons weren't in the test. The fix ships that afternoon with a note. Nobody's surprised. The client's confidence went up, not down, because the miss was already on the list of things we told them we hadn't checked.\n\nThe detriment is what happens when you get the sort wrong. Let a checkout bug through under \"minor\" and the client doesn't hear \"we move fast.\" They hear \"the unresponsive web guy strikes again.\" The cure is a better sort, not more process.\n\n### Startup and personal projects: speed, with a feedback loop that actually loops\n\nAt this tier, speed is the lever. Prove the dominant path works, ship it, and watch. Edge cases get found by users. That isn't a failure of QA. It's the QA strategy, and it's a good one if you hold up your end.\n\nHolding up your end means you respond in hours, not sprints. You tell the user what happened and when it'll be fixed. Then you fix it and tell them it's fixed. Do that, and a bug report becomes one of the best moments in the customer relationship. The user just watched their feedback change the product they're paying for. Engineers get to move quickly on things that matter. Nobody spent a week testing a page nobody visits.\n\nTesting in production is the honest name for this approach. It works when you have monitoring, a way to hear from users, and someone who will act on what they hear. Without those three, \"move fast\" is just \"ship bugs.\"\n\nPicture the first ten users of a scheduling tool. One of them books an appointment that crosses midnight and the confirmation shows the wrong day. They email. Within the hour they get a reply: \"Good catch, you're the first person to book across midnight, fix is going out today.\" That evening it's fixed and they get a second note. That user tells two people about the tool. Not because it was bug-free. Because someone was there.\n\nThe detriment is the same approach without the loop. A bug that sits for three weeks with no reply is the exact experience that sends people looking for a new developer. And \"it's only a prototype\" stops applying the moment a customer is in a meeting looking at it, which is precisely what the demo story was.\n\n### The rule that holds at every tier\n\nState what was tested and what wasn't. Make residual risk visible before release. Respond fast when something gets through. The tiers change how much you test. They don't change whether you own the answer.\n\n## Quality is a risk decision, not a checkbox\n\nNone of this argues that every engineer must exhaustively test every state. Time, environment access, test data, specialist hardware, security controls, and third-party dependencies limit what one person can prove alone. The standard is:\n\n1. Test the highest-value and highest-frequency paths available to you.\n2. Automate repeatable checks where the value justifies it.\n3. State what was tested and what was not.\n4. Make residual risk visible before release.\n5. Escalate when meaningful validation needs access, expertise, or an environment you don't have.\n\nQuality can be shared across a team. It can't be unowned.\n\n## The lesson from the demo\n\nThe lesson wasn't that development must never break. Development exists so we can find problems safely. The lesson was that a feature isn't validated because we found one account that could make it work. Engineering quality means choosing tests that represent real use and leaving shared systems ready for the next person. It also means being honest about the evidence behind the word \"done.\"\n\nIf you run a business where real money moves through the site and nobody is sorting your paths by what they cost when they break, that's the first conversation we have on a call.","https:\u002F\u002Fcmdcntr.io\u002Fcovers\u002Fai-best-practices\u002Fqa-is-part-of-the-build.webp","A chrome drafting compass standing upright, fused to a chrome blueprint sheet, whole and cleanly engineered, with electric violet binary code and thin wires running into the blueprint grid and a single cyan guidance trace, on a near-black floor etched with circuit traces.",[17,18,19,20,21],"qa","testing","definition of done","ai code","best practices",[],[24,27,30,33],{"answer":25,"question":26},"The team that does the work. In Scrum that's the whole Scrum team, sometimes with an organization-wide minimum layered on top. In practice, the engineers who ship changes should write the QA half of it, because they're the ones who have to answer \"what did this test prove?\"","Who creates the definition of done?",{"answer":28,"question":29},"Yes, and it shouldn't be the only test. The developer proves the dominant path and hands over evidence. Then someone who didn't build it tests with fresh eyes: a QA engineer, a teammate, or the client in staging. The builder has looked at that screen a few hundred times and has stopped seeing it.","Should developers test their own code?",{"answer":31,"question":32},"Enough to prove the path most users take, plus a working way to hear about the rest. That means monitoring and a feedback channel someone actually reads. It also means fixing reported bugs in hours. That loop is the startup's QA department.","How much QA does a startup need?",{"answer":34,"question":35},"More scrutiny, not necessarily more test cases. The code arrives faster, so the human's job shifts to choosing representative scenarios and deciding what evidence is enough. Start with the paths most users take and work outward from there.","Does AI-generated code need more testing or less?",false,"published","QA Is Part of the Build: Testing in the Definition of Done","A failed demo, a borrowed admin account, and the QA habit engineers need: test the user's path, not just the code. Plus QA strategy by company stage.","https:\u002F\u002Fcmdcntr.io\u002Fblog\u002Fai-best-practices\u002Fqa-is-part-of-the-build","2026-09-11T20:29:49.653Z","7452d3cc-b0aa-46e4-96e6-da9c0225c471","2026-09-11T17:52:39.289Z","ed80da88-f3d1-4aa9-9373-18c39fecb740","ffab1f0c-63d8-41e8-b3e4-87e028178c8e","c0fcf6a1-58d2-4262-8996-3ad29d58eea5",{"slug":48,"name":49,"avatarUrl":50,"role":51,"bio":52,"isPublic":53,"expertiseSummary":54,"linkedin":55,"github":56,"twitter":12,"website":57},"michael-graham","Michael Graham","\u002Fapi\u002Fpublic\u002Favatar\u002F7452d3cc-b0aa-46e4-96e6-da9c0225c471","Founder & Software Engineer","Obsessed with building top-tier web software and crafting unique, polished user experiences.",true,"From frontend design to a fully deployed application, I can build the entire pipeline.","https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fmikemartire\u002F","https:\u002F\u002Fgithub.com\u002Fmichaelchristophergraham","https:\u002F\u002Fcmdcntr.io",{"slug":59,"name":60,"color":61},"ai-best-practices","AI Best Practices","#EC4899",{"id":46,"name":63,"ctaType":64,"heading":65,"description":66,"buttonText":67,"url":5,"leadMagnetUrl":12},"Book a Call (blog)","book_call","Shipping AI-generated code that keeps breaking?","Book a free 30-minute call with a senior engineer. We diagnose what is going wrong and give you a concrete fix plan, no obligation.","Book a free call",[],[70],{"id":71,"slug":72,"title":73,"description":74,"coverImageUrl":75,"coverImageAlt":76,"tags":77,"featured":36,"tool":12,"publishedAt":81,"author":82,"cluster":83},"12e12c27-422a-415a-8dcd-08ad886a6f91","ai-generated-ui-components-fail-wcag-2-2-review-checklist","AI-Generated UI Components Fail WCAG 2.2: The Review Checklist That Catches It","AI tools generate UI components that look right and fail WCAG 2.2 at scale, for the same reason they skip security. Here is the fast review checklist that catches it before merge.","https:\u002F\u002Fcmdcntr.io\u002Fcovers\u002Fenterprise-cms\u002Fai-components.webp","A chrome user-interface element shattering with purple energy and streaming code spilling out",[20,78,79,80,21],"accessibility","wcag","code review","2026-06-10T14:00:00.000Z",{"slug":48,"name":49,"avatarUrl":50,"role":51,"bio":52,"isPublic":53},{"slug":59,"name":60,"color":61},{"data":85,"body":86},{},{"type":87,"children":88},"root",[89,103,110,115,120,125,130,135,141,146,151,156,165,170,176,181,188,193,199,204,210,215,221,226,261,270,276,281,287,292,297,302,307,313,318,340,353,359,367,372,377,484,490,495,500,505,510,516,521,526,531,536,541,547,552,557,562,567,572,578,583,589,594,623,628,634,639],{"type":90,"tag":91,"props":92,"children":93},"element","p",{},[94,101],{"type":90,"tag":95,"props":96,"children":97},"strong",{},[98],{"type":99,"value":100},"text","The short answer.",{"type":99,"value":102}," Quality assurance is not a checkpoint at the end that someone else owns. It is part of the engineer's definition of done, and it starts with proving the software works for the people and paths that carry most of the real traffic. How much proof you need depends on the size of the company and what a bug costs. Who owns the answer never changes.",{"type":90,"tag":104,"props":105,"children":107},"h2",{"id":106},"the-demo-that-didnt-happen",[108],{"type":99,"value":109},"The demo that didn't happen",{"type":90,"tag":91,"props":111,"children":112},{},[113],{"type":99,"value":114},"When I came back from leave, I joined a customer meeting expecting to walk through part of a platform my team had been building. Instead, the shared development environment was unusable for the demo. The account shown as the administrator had the wrong email address on it. The tenant switcher wasn't reliable enough to reach the tenant we needed.",{"type":90,"tag":91,"props":116,"children":117},{},[118],{"type":99,"value":119},"The email mismatch wasn't an accident. A developer had put their own address on the administrator account to test email notifications and hadn't put the shared data back. The feature had been exercised through the admin account, even though standard users are the people most likely to subscribe to those notifications in real use.",{"type":90,"tag":91,"props":121,"children":122},{},[123],{"type":99,"value":124},"None of this was catastrophic. It was development, not production, and the immediate problem got fixed. That's exactly why it was worth talking about. Development is where we build the habits that eventually reach production.",{"type":90,"tag":91,"props":126,"children":127},{},[128],{"type":99,"value":129},"The useful question wasn't \"did the notification send?\" It was \"did we prove the feature works the way our users are most likely to use it?\"",{"type":90,"tag":91,"props":131,"children":132},{},[133],{"type":99,"value":134},"I want to be fair to the developer here. They took the feedback well and agreed to test the other roles. The conversation was about the pattern, not the person. I've caused production incidents of my own. That is the reason I care about building this habit early, while the blast radius is still small.",{"type":90,"tag":104,"props":136,"children":138},{"id":137},"did-we-test-the-feature-or-did-we-test-the-users-path",[139],{"type":99,"value":140},"Did we test the feature, or did we test the user's path?",{"type":90,"tag":91,"props":142,"children":143},{},[144],{"type":99,"value":145},"Testing a feature is not the same as testing user behavior.",{"type":90,"tag":91,"props":147,"children":148},{},[149],{"type":99,"value":150},"An administrator account is often the fastest route to a screen or a permission. If administrators aren't the primary users of the feature, a green admin test proves an edge path. It says nothing about the dominant one. Permissions, tenant context, seed data, navigation, and account state can all hide behind a passing result.",{"type":90,"tag":91,"props":152,"children":153},{},[154],{"type":99,"value":155},"This is the mentality I want engineers to carry:",{"type":90,"tag":157,"props":158,"children":159},"blockquote",{},[160],{"type":90,"tag":91,"props":161,"children":162},{},[163],{"type":99,"value":164},"Don't ask only whether the code can work. Ask whether we have evidence that it works for the user, role, data, and environment that will carry most of the real traffic.",{"type":90,"tag":91,"props":166,"children":167},{},[168],{"type":99,"value":169},"For the notification feature, that means seeding a standard user, subscribing as that user, triggering the notification, and confirming the outcome from that user's side of the screen. The admin test is extra coverage. It isn't the main proof.",{"type":90,"tag":104,"props":171,"children":173},{"id":172},"what-qa-is-part-of-the-build-means-in-practice",[174],{"type":99,"value":175},"What \"QA is part of the build\" means in practice",{"type":90,"tag":91,"props":177,"children":178},{},[179],{"type":99,"value":180},"Five habits. None of them require a QA department.",{"type":90,"tag":182,"props":183,"children":185},"h3",{"id":184},"start-with-the-dominant-user-journey",[186],{"type":99,"value":187},"Start with the dominant user journey",{"type":90,"tag":91,"props":189,"children":190},{},[191],{"type":99,"value":192},"Figure out who uses the feature most and test that path first. Secondary roles and edge cases still matter. They extend coverage. They don't substitute for the primary journey.",{"type":90,"tag":182,"props":194,"children":196},{"id":195},"treat-a-shared-dev-environment-like-a-product-when-people-depend-on-it",[197],{"type":99,"value":198},"Treat a shared dev environment like a product when people depend on it",{"type":90,"tag":91,"props":200,"children":201},{},[202],{"type":99,"value":203},"\"It's only dev\" is a fair statement about blast radius. It's not a reason to leave the environment in an unknown state. If customers, product owners, or other developers use it for demos and acceptance, it has an operational purpose. Until a production environment exists, dev may be the most visible version of the product there is. Its reliability affects trust even when no production data is at risk.",{"type":90,"tag":182,"props":205,"children":207},{"id":206},"cleanup-is-part-of-the-test",[208],{"type":99,"value":209},"Cleanup is part of the test",{"type":90,"tag":91,"props":211,"children":212},{},[213],{"type":99,"value":214},"A test that mutates shared data isn't finished when the assertion passes. It's finished when the environment is restored or the temporary data is isolated. Prefer disposable test users and repeatable seed data over editing shared identities. When temporary data is unavoidable, put the cleanup in the same change or the same workflow. A cleanup pull request should be the exception, not the mechanism.",{"type":90,"tag":182,"props":216,"children":218},{"id":217},"a-passing-check-is-not-the-same-as-enough-evidence",[219],{"type":99,"value":220},"A passing check is not the same as enough evidence",{"type":90,"tag":91,"props":222,"children":223},{},[224],{"type":99,"value":225},"One passing scenario answers one narrow question. Engineering judgment is deciding whether that question is representative enough to support release confidence. Before you call something done, run through this:",{"type":90,"tag":227,"props":228,"children":229},"ul",{},[230,236,241,246,251,256],{"type":90,"tag":231,"props":232,"children":233},"li",{},[234],{"type":99,"value":235},"Who is the primary user?",{"type":90,"tag":231,"props":237,"children":238},{},[239],{"type":99,"value":240},"What is their most common path?",{"type":90,"tag":231,"props":242,"children":243},{},[244],{"type":99,"value":245},"Which permissions, tenant state, and data does that path depend on?",{"type":90,"tag":231,"props":247,"children":248},{},[249],{"type":99,"value":250},"What did this test actually prove?",{"type":90,"tag":231,"props":252,"children":253},{},[254],{"type":99,"value":255},"What could still fail even though it passed?",{"type":90,"tag":231,"props":257,"children":258},{},[259],{"type":99,"value":260},"Did the test leave shared state clean and predictable?",{"type":90,"tag":91,"props":262,"children":263},{},[264],{"type":90,"tag":265,"props":266,"children":269},"img",{"alt":267,"src":268},"The six-question pre-release check laid out as a numbered checklist in two columns. One: who is the primary user, meaning the role that carries most of the real traffic, not the fastest account to reach the screen. Two: what is their most common path, which gets tested first while secondary roles and edge cases extend coverage rather than replace it. Three: which permissions, tenant state, and data does that path depend on, since all of them can hide behind a green result. Four: what did this test actually prove, because an admin test of a feature built for standard users proves an edge path. Five: what could still fail even though it passed, naming the residual risk before release. Six: did the test leave shared state clean and predictable, because a test that mutates shared data is finished when the environment is restored, not when the assertion passes.","\u002Fcovers\u002Fai-best-practices\u002Fvisuals\u002Fqa-pre-release-check.webp",[],{"type":90,"tag":182,"props":271,"children":273},{"id":272},"engineers-own-quality-even-when-a-qa-role-exists",[274],{"type":99,"value":275},"Engineers own quality even when a QA role exists",{"type":90,"tag":91,"props":277,"children":278},{},[279],{"type":99,"value":280},"Dedicated QA people bring independence and exploratory thinking the builder doesn't have. Their involvement doesn't move ownership. The person who implemented the change is responsible for understanding its behavior, testing the expected paths, and handing over evidence that it's ready for broader validation. QA deepens and challenges that evidence. It should never be the first time anyone asks whether the feature works the way a real user would use it.",{"type":90,"tag":104,"props":282,"children":284},{"id":283},"why-is-it-important-to-establish-a-definition-of-done",[285],{"type":99,"value":286},"Why is it important to establish a definition of done?",{"type":90,"tag":91,"props":288,"children":289},{},[290],{"type":99,"value":291},"A definition of done is the shared checklist a change has to clear before the team calls it finished. It matters because without one, \"done\" means whatever the last person to touch the work decided it meant. Putting QA inside that definition is what stops testing from turning into a handoff.",{"type":90,"tag":91,"props":293,"children":294},{},[295],{"type":99,"value":296},"Most teams already have some version of this. Code written, reviewed, merged. The gap I see over and over is that \"tested\" sits in the list as a single word and nobody has agreed on what it means. Tested by whom? As which user? With what data? In which environment, and was that environment left the way you found it?",{"type":90,"tag":91,"props":298,"children":299},{},[300],{"type":99,"value":301},"If your definition of done doesn't answer those questions, your QA is a vibe. Add the six questions above and you've turned a word into a standard. That's the whole change.",{"type":90,"tag":91,"props":303,"children":304},{},[305],{"type":99,"value":306},"One distinction worth keeping straight: acceptance criteria describe what one feature has to do. The definition of done describes what every change has to clear. QA belongs in the second one, so it applies whether or not anyone remembered to write a test case into the ticket.",{"type":90,"tag":104,"props":308,"children":310},{"id":309},"ai-raises-the-cost-of-a-weak-quality-mentality",[311],{"type":99,"value":312},"AI raises the cost of a weak quality mentality",{"type":90,"tag":91,"props":314,"children":315},{},[316],{"type":99,"value":317},"AI can produce code faster than a team can understand and validate it. If engineers treat generated code as finished code, output goes up and confidence goes down. The bottleneck moves from writing syntax to exercising judgment: picking representative scenarios, noticing the missing case, questioning assumptions, and deciding what evidence is enough.",{"type":90,"tag":91,"props":319,"children":320},{},[321,323,330,332,338],{"type":99,"value":322},"We've written about what this looks like when the missing case is ",{"type":90,"tag":324,"props":325,"children":327},"a",{"href":326},"\u002Fblog\u002Ffix-ai-code\u002Fwhy-ai-generated-authentication-breaks",[328],{"type":99,"value":329},"a security boundary in AI-generated authentication",{"type":99,"value":331}," or ",{"type":90,"tag":324,"props":333,"children":335},{"href":334},"\u002Fblog\u002Fai-best-practices\u002Fai-generated-ui-components-fail-wcag-2-2-review-checklist",[336],{"type":99,"value":337},"an accessibility affordance in a generated UI component",{"type":99,"value":339},". It's the same pattern as the admin account. The tool optimized for the path in front of it. The path in front of it was not the path most users take.",{"type":90,"tag":91,"props":341,"children":342},{},[343,345,351],{"type":99,"value":344},"The more implementation we hand to AI, the more deliberately humans have to own validation. AI changes how code gets produced. It doesn't change who is accountable for the result. If you're moving a vibe-coded app toward real users, ",{"type":90,"tag":324,"props":346,"children":348},{"href":347},"\u002Fblog\u002Fvibe-coding\u002Fvibe-code-to-production-migration-playbook",[349],{"type":99,"value":350},"the migration playbook",{"type":99,"value":352}," walks through where that scrutiny goes first.",{"type":90,"tag":104,"props":354,"children":356},{"id":355},"qa-strategy-by-company-stage-enterprise-smb-and-startup",[357],{"type":99,"value":358},"QA strategy by company stage: enterprise, SMB, and startup",{"type":90,"tag":91,"props":360,"children":361},{},[362],{"type":90,"tag":265,"props":363,"children":366},{"alt":364,"src":365},"Three cards comparing QA strategy by company stage. Enterprise and large SaaS: a bug costs contracts, renewals, and reputation at scale, so QA is heavy with regression suites, staging that mirrors production, release gates, and sign-offs, and speed comes from parallel teams and automation rather than the release process. Mature SMB: a bug costs a lost order, a support ticket, or a client's confidence, so QA is balanced with full coverage on revenue paths and lighter elsewhere, and speed comes from client review in staging, small batches, and fast fixes. Startup or personal project: a bug costs a day of a founder's time and occasionally a user, so QA is light with the dominant path proven and everything else watched, and speed comes from shipping first, fixing in hours, and talking to users. Footer: the tiers change how much you test, not whether you own the answer.","\u002Fcovers\u002Fai-best-practices\u002Fvisuals\u002Fqa-strategy-by-company-stage.webp",[],{"type":90,"tag":91,"props":368,"children":369},{},[370],{"type":99,"value":371},"How much QA you need is a function of what a bug costs and who absorbs it. Enterprise and large software-as-a-service (SaaS) companies front-load quality because the software is the product, so they accept slower delivery. A mature small or mid-sized business (SMB) balances the two. A startup or side project leans on speed and uses a fast customer feedback loop as part of its QA. Every tier still owns the answer to \"what did we prove?\"",{"type":90,"tag":91,"props":373,"children":374},{},[375],{"type":99,"value":376},"I've shipped code at billion-dollar companies and for two-person startups. The QA mentality is the same at both. The amount of process wrapped around it is not, and pretending otherwise is how teams either drown in ceremony or ship checkout bugs.",{"type":90,"tag":378,"props":379,"children":380},"table",{},[381,410],{"type":90,"tag":382,"props":383,"children":384},"thead",{},[385],{"type":90,"tag":386,"props":387,"children":388},"tr",{},[389,395,400,405],{"type":90,"tag":390,"props":391,"children":392},"th",{},[393],{"type":99,"value":394},"Tier",{"type":90,"tag":390,"props":396,"children":397},{},[398],{"type":99,"value":399},"What a bug costs",{"type":90,"tag":390,"props":401,"children":402},{},[403],{"type":99,"value":404},"How much QA",{"type":90,"tag":390,"props":406,"children":407},{},[408],{"type":99,"value":409},"Where the speed comes from",{"type":90,"tag":411,"props":412,"children":413},"tbody",{},[414,438,461],{"type":90,"tag":386,"props":415,"children":416},{},[417,423,428,433],{"type":90,"tag":418,"props":419,"children":420},"td",{},[421],{"type":99,"value":422},"Enterprise \u002F large SaaS",{"type":90,"tag":418,"props":424,"children":425},{},[426],{"type":99,"value":427},"Contracts, renewals, reputation at scale",{"type":90,"tag":418,"props":429,"children":430},{},[431],{"type":99,"value":432},"Heavy. Regression suites, staging that mirrors production, release gates, sign-offs",{"type":90,"tag":418,"props":434,"children":435},{},[436],{"type":99,"value":437},"Not from the release process. From parallel teams and automation",{"type":90,"tag":386,"props":439,"children":440},{},[441,446,451,456],{"type":90,"tag":418,"props":442,"children":443},{},[444],{"type":99,"value":445},"Mature SMB",{"type":90,"tag":418,"props":447,"children":448},{},[449],{"type":99,"value":450},"A lost order, a support ticket, a client's confidence",{"type":90,"tag":418,"props":452,"children":453},{},[454],{"type":99,"value":455},"Balanced. Full coverage on revenue paths, lighter everywhere else",{"type":90,"tag":418,"props":457,"children":458},{},[459],{"type":99,"value":460},"Client review in staging, small batches, fast fixes",{"type":90,"tag":386,"props":462,"children":463},{},[464,469,474,479],{"type":90,"tag":418,"props":465,"children":466},{},[467],{"type":99,"value":468},"Startup \u002F personal project",{"type":90,"tag":418,"props":470,"children":471},{},[472],{"type":99,"value":473},"A day of a founder's time, occasionally a user",{"type":90,"tag":418,"props":475,"children":476},{},[477],{"type":99,"value":478},"Light. Dominant path proven, everything else watched",{"type":90,"tag":418,"props":480,"children":481},{},[482],{"type":99,"value":483},"Shipping first, fixing in hours, talking to users",{"type":90,"tag":182,"props":485,"children":487},{"id":486},"enterprise-and-large-saas-satisfaction-is-the-product",[488],{"type":99,"value":489},"Enterprise and large SaaS: satisfaction is the product",{"type":90,"tag":91,"props":491,"children":492},{},[493],{"type":99,"value":494},"When the software is the entire product, satisfaction with the software is the entire business. Every renewal depends on it. So the process front-loads quality. Regression suites that take hours. Staging environments that mirror production. Release trains. Sign-offs from people who never touched the code. A small fix can take weeks to reach a customer.",{"type":90,"tag":91,"props":496,"children":497},{},[498],{"type":99,"value":499},"That slowness isn't incompetence. It's a decision that a bug at scale costs more than waiting does. AI doesn't change that math. It makes more code arrive at the gate. It doesn't make the gate cheaper, because the gate exists to catch what the author didn't think of, and the author is now sometimes a model.",{"type":90,"tag":91,"props":501,"children":502},{},[503],{"type":99,"value":504},"How customers are treated at this tier: they should never be the ones finding the bug. Communication is formal and scheduled. Status pages, release notes, an account manager who calls before you notice.",{"type":90,"tag":91,"props":506,"children":507},{},[508],{"type":99,"value":509},"The detriment shows up when process built for the big release gets applied to the one-line fix. Engineers stop testing with intent because \"QA will catch it.\" That is the failure mode from the demo story in miniature, and it happens at every company size.",{"type":90,"tag":182,"props":511,"children":513},{"id":512},"mature-smb-balance-and-be-honest-about-which-paths-matter",[514],{"type":99,"value":515},"Mature SMB: balance, and be honest about which paths matter",{"type":90,"tag":91,"props":517,"children":518},{},[519],{"type":99,"value":520},"This is most of our clients at Command Center. Real revenue moves through the site. There's no QA department, and there never will be one. So the strategy is to sort paths by what they cost when they break.",{"type":90,"tag":91,"props":522,"children":523},{},[524],{"type":99,"value":525},"Revenue paths get the enterprise treatment. Checkout, lead forms, login, anything that sends an email a customer is waiting on. Those get tested as the actual user, with realistic data, in staging. The client sees it working before it goes live. Our staging, review, then live workflow exists because of this tier. The client reviewing in staging is a QA step, and it's the one that catches the \"that's not how our customers use it\" bug an engineer can't see from inside the code.",{"type":90,"tag":91,"props":527,"children":528},{},[529],{"type":99,"value":530},"Everything else gets a lighter pass, and we say so. A layout glitch on a page that gets thirty visits a month can ship. The client hears \"we tested the checkout end to end on desktop and mobile; we did not test the archive page on every phone.\" That sentence is the difference between a client who trusts you and one who feels ambushed.",{"type":90,"tag":91,"props":532,"children":533},{},[534],{"type":99,"value":535},"Here's the shape of a typical week. A client asks for a change to how shipping gets calculated. We build it in staging, run three real orders through as a customer would (not as the store admin), and send the client a short screen recording plus a note listing what we tried. They place a test order themselves. It goes live the next morning. Two days later they report that a specific coupon combination shows the wrong total. We had said coupons weren't in the test. The fix ships that afternoon with a note. Nobody's surprised. The client's confidence went up, not down, because the miss was already on the list of things we told them we hadn't checked.",{"type":90,"tag":91,"props":537,"children":538},{},[539],{"type":99,"value":540},"The detriment is what happens when you get the sort wrong. Let a checkout bug through under \"minor\" and the client doesn't hear \"we move fast.\" They hear \"the unresponsive web guy strikes again.\" The cure is a better sort, not more process.",{"type":90,"tag":182,"props":542,"children":544},{"id":543},"startup-and-personal-projects-speed-with-a-feedback-loop-that-actually-loops",[545],{"type":99,"value":546},"Startup and personal projects: speed, with a feedback loop that actually loops",{"type":90,"tag":91,"props":548,"children":549},{},[550],{"type":99,"value":551},"At this tier, speed is the lever. Prove the dominant path works, ship it, and watch. Edge cases get found by users. That isn't a failure of QA. It's the QA strategy, and it's a good one if you hold up your end.",{"type":90,"tag":91,"props":553,"children":554},{},[555],{"type":99,"value":556},"Holding up your end means you respond in hours, not sprints. You tell the user what happened and when it'll be fixed. Then you fix it and tell them it's fixed. Do that, and a bug report becomes one of the best moments in the customer relationship. The user just watched their feedback change the product they're paying for. Engineers get to move quickly on things that matter. Nobody spent a week testing a page nobody visits.",{"type":90,"tag":91,"props":558,"children":559},{},[560],{"type":99,"value":561},"Testing in production is the honest name for this approach. It works when you have monitoring, a way to hear from users, and someone who will act on what they hear. Without those three, \"move fast\" is just \"ship bugs.\"",{"type":90,"tag":91,"props":563,"children":564},{},[565],{"type":99,"value":566},"Picture the first ten users of a scheduling tool. One of them books an appointment that crosses midnight and the confirmation shows the wrong day. They email. Within the hour they get a reply: \"Good catch, you're the first person to book across midnight, fix is going out today.\" That evening it's fixed and they get a second note. That user tells two people about the tool. Not because it was bug-free. Because someone was there.",{"type":90,"tag":91,"props":568,"children":569},{},[570],{"type":99,"value":571},"The detriment is the same approach without the loop. A bug that sits for three weeks with no reply is the exact experience that sends people looking for a new developer. And \"it's only a prototype\" stops applying the moment a customer is in a meeting looking at it, which is precisely what the demo story was.",{"type":90,"tag":182,"props":573,"children":575},{"id":574},"the-rule-that-holds-at-every-tier",[576],{"type":99,"value":577},"The rule that holds at every tier",{"type":90,"tag":91,"props":579,"children":580},{},[581],{"type":99,"value":582},"State what was tested and what wasn't. Make residual risk visible before release. Respond fast when something gets through. The tiers change how much you test. They don't change whether you own the answer.",{"type":90,"tag":104,"props":584,"children":586},{"id":585},"quality-is-a-risk-decision-not-a-checkbox",[587],{"type":99,"value":588},"Quality is a risk decision, not a checkbox",{"type":90,"tag":91,"props":590,"children":591},{},[592],{"type":99,"value":593},"None of this argues that every engineer must exhaustively test every state. Time, environment access, test data, specialist hardware, security controls, and third-party dependencies limit what one person can prove alone. The standard is:",{"type":90,"tag":595,"props":596,"children":597},"ol",{},[598,603,608,613,618],{"type":90,"tag":231,"props":599,"children":600},{},[601],{"type":99,"value":602},"Test the highest-value and highest-frequency paths available to you.",{"type":90,"tag":231,"props":604,"children":605},{},[606],{"type":99,"value":607},"Automate repeatable checks where the value justifies it.",{"type":90,"tag":231,"props":609,"children":610},{},[611],{"type":99,"value":612},"State what was tested and what was not.",{"type":90,"tag":231,"props":614,"children":615},{},[616],{"type":99,"value":617},"Make residual risk visible before release.",{"type":90,"tag":231,"props":619,"children":620},{},[621],{"type":99,"value":622},"Escalate when meaningful validation needs access, expertise, or an environment you don't have.",{"type":90,"tag":91,"props":624,"children":625},{},[626],{"type":99,"value":627},"Quality can be shared across a team. It can't be unowned.",{"type":90,"tag":104,"props":629,"children":631},{"id":630},"the-lesson-from-the-demo",[632],{"type":99,"value":633},"The lesson from the demo",{"type":90,"tag":91,"props":635,"children":636},{},[637],{"type":99,"value":638},"The lesson wasn't that development must never break. Development exists so we can find problems safely. The lesson was that a feature isn't validated because we found one account that could make it work. Engineering quality means choosing tests that represent real use and leaving shared systems ready for the next person. It also means being honest about the evidence behind the word \"done.\"",{"type":90,"tag":91,"props":640,"children":641},{},[642],{"type":99,"value":643},"If you run a business where real money moves through the site and nobody is sorting your paths by what they cost when they break, that's the first conversation we have on a call."]