Skip to content

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