Completeness Checking¶
Why It Matters¶
Most specifications are incomplete - they describe the happy path and a few error cases, leaving edge cases undefined. These gaps are where bugs hide. Completeness checking forces you to ask "what happens if...?" for every possible scenario, exposing the cases you didn't think about.
The Key Move¶
For any specification, enumerate all possible inputs/states by partitioning the space exhaustively. For each partition, explicitly state what happens. Check that partitions are mutually exclusive (no overlap) and collectively exhaustive (no gaps). Flag any case marked "undefined" or "shouldn't happen" as requiring either explicit handling or documented assumptions.
Classic Application¶
Protocol specification. TCP's state machine defines exactly what happens for every packet in every state. If a FIN arrives in LISTEN state, it's not "weird" or "shouldn't happen" - there's a defined response. This completeness is why TCP implementations interoperate despite being written by different teams.
Surprising Application¶
Decision-making frameworks. "Follow your passion" is incomplete - what if you have no passion? multiple passions? expensive passions? A complete framework must handle all cases: strong single passion (pursue it), multiple passions (portfolio approach), unclear passion (experiment systematically), no passion (optimize for craft/contribution).
Failure Modes¶
Combinatorial explosion - trying to enumerate too finely, creating unmanageable case counts. False completeness - partitioning by irrelevant dimensions while missing the critical distinctions. Analysis paralysis from insisting on completeness where approximate coverage suffices.
Go Deeper¶
Jackson, Software Abstractions, Chapter 3; Lamport, Specifying Systems, Chapter 5