{"id":"2074047145859228099","url":"https://x.com/nurijanian/status/2074047145859228099","text":"","author":{"name":"George from 🕹prodmgmt.world","username":"nurijanian","avatarUrl":"https://pbs.twimg.com/profile_images/1602541464851980288/Stnr4-Bl_200x200.png"},"createdAt":"Mon Jul 06 08:25:48 +0000 2026","engagement":{"replies":3,"retweets":21,"likes":232,"views":34220},"article":{"title":"/edge-cases: a simple skill to catch missed edge cases","previewText":"There's a real PRD sitting in my examples folder, a Shopify to QuickBooks connector, and buried in feature one it says this, word for word:\n\"there could be 2 or more orders, whose aggregate sum should","coverImageUrl":"https://pbs.twimg.com/media/HMh-1CIbQAAb4MZ.jpg","content":"There's a real PRD sitting in my examples folder, a Shopify to QuickBooks connector, and buried in feature one it says this, word for word:\n\n> \"there could be 2 or more orders, whose aggregate sum should equal the payout amount. (if it doesn't then something is wrong 😁)\"\n\nAn emoji. Where the error handling should be. The PRD names its own failure condition, the money doesn't add up, and then specifies nothing about what the system should do when it happens. Smiley face, next feature.\n\nAnd honestly, I get it. A human engineer reads that line, snorts, and asks in refinement: \"so what do we do when the sums don't match?\" The gap becomes a question, the question becomes an answer, and all of that happens before anything ships. That emoji was load-bearing for years and nobody noticed, because there was always a human on the other end to catch it.\n\nAn AI coding agent doesn't snort. Feed Claude or Cursor that PRD and it won't pause at the 😁. It picks something plausible, log a warning, book the invoices anyway, writes it with full confidence, and moves on to the next feature. The code compiles, because the tests you didn't write can't fail. Nobody finds out until the books don't reconcile.\n\n## so what changed about writing specs?\n\nI think what I arrive at is this: the reason you write specs has changed, or at least the failure mode has. A human reader plus an incomplete spec produces a follow-up question, which is annoying but recoverable. An agent reader plus an incomplete spec ships wrong code anyway, and that's much harder to catch.\n\nThe PM writing specs for an eng team had a backstop they probably never noticed they had: someone else's confusion. The PM writing specs for an agent has that backstop removed. Nobody took it away on purpose, it just quietly isn't there anymore.\n\n## the pass I ran on it\n\nThe fix isn't \"think harder about edge cases\" as a vague note to yourself before refinement. I've written that note. It doesn't work. What does work, as far as I can tell, is a structured pass across eight categories, every time, in the same order: user types, contexts of use, unexpected inputs and system failures, user error, feature interactions, load, security and privacy, accessibility. The order matters because it catches the categories you personally always forget, and everyone has ones they always forget.\n\nSo I ran that pass on the connector PRD. The spec itself looks done: eight features, links to the right Shopify and QuickBooks API docs, and one acceptance test. A $2,000 payout with three transactions becomes three invoices in QuickBooks, each carrying the Shopify ID, total, tax, discount, shipping, and a link back to the order. Reads complete. Reads like it's ready to hand to an agent.\n\nThe pass came back with 27 scenarios. Here are three full rows, and next to each one, my honest guess at what an agent would ship if the spec stays silent.\n\nThe 😁 line itself. Scenario: sum of transactions ≠ payout amount. Expected behavior from the pass: halt booking for that payout, mark it \"Reconciliation failed\" in the admin UI with both figures and the delta, notify the admin, and critically, do NOT book the invoices that happen to match and silently skip the rest. What an agent ships instead: a log line and full speed ahead, because \"something is wrong 😁\" contains no instruction to stop.\n\nThe refund. Scenario: a $2,000 payout that's really $2,300 in charges minus a $300 refund. Expected: the refund becomes a QuickBooks credit memo, and charges plus refunds plus fees still reconcile to the payout total before anything is written. What an agent ships: a $-300 \"invoice,\" or the refund silently skipped, because the spec's only test contains three clean charges and nothing else.\n\nThe tag. Scenario: an admin hand-adds a \"Booked\" tag to an order the connector never processed. Expected: the tag is never read as the source of truth, the connector keeps its own processed ledger, so the mistagged order still gets invoiced. What an agent ships: the tag as state, because the acceptance test checks that the tag appears and it's the only state signal the spec ever mentions. One fat-fingered tag and that order drops out of invoicing forever, silently.\n\nThree more misses came out of the same run, and they rhyme: a re-run creating duplicate invoices because nothing demands idempotency, an auth failure leaving a payout half-booked with no checkpoint, and NZD amounts written into a USD QuickBooks file because the test never names a currency. Six gaps total, and the spec's one acceptance test, the clean $2,000 payout, passes straight through every one of them.\n\n## is any of this genius? no\n\nHere's the objection I'd raise myself: a good senior engineer would catch most of these. Idempotency, rate limits, token refresh, that's table stakes for anyone who's built an integration. If the bar is \"insight no engineer could produce,\" this pass doesn't clear it, and I don't think any checklist ever will.\n\nThat was never the job, though. The job is that this table exists before refinement, produced by the person who wrote the spec, instead of surfacing one gap at a time across three refinement calls, or worse, not surfacing at all because the reader was an agent and agents don't snort at emojis. The pass took twenty minutes. The alternative was six defined-behavior decisions getting made implicitly, by a code generator, at 2 a.m., inside somebody's accounting system.\n\nAnd the misses aren't random. Every one of them is the same question wearing different clothes: what happens when the money doesn't add up the way the happy path assumed. If I were to theorize about why the spec missed all six, I'd guess it's because the happy path only ever contains clean charges, and real payouts contain refunds, fees, adjustments, and someone's fat-fingered tag.\n\n## the one move\n\nSo before the next spec goes into refinement, or gets pasted into an agent's context window, run the eight categories against it. You walk away with something concrete to send: a comment to the eng channel naming the scenarios the spec didn't cover, asking for defined behavior on each. Skip that comment and the same gap still surfaces later, mid-call, with your name on the spec. You end up saying \"let's take it offline\" about a document you wrote yourself, which I've done, and it's not a good feeling.\n\nHonestly, the hard part isn't knowing edge cases exist. Everyone knows edge cases exist. The hard part is sitting down and running the full eight-category pass on every spec when refinement starts in forty minutes.\n\n![](https://pbs.twimg.com/media/HMh7TuFbAAElLQ6.jpg)\n\nPM OS ships that pass as a ready skill that runs on your company context, so the scenario table comes back shaped by your product and your users, not a plain checklist. \n\nThe spec-hardening layer sits next to the workflows for strategy, research, and decisions. \n\n## [Get it and install today.](https://prodmgmt.world/x/case-spec-missed_070726)"}}