Get the FREE Ultimate OpenClaw Setup Guide →

making-invalid-states-unrepresentable

npx machina-cli add skill msewell/agent-stuff/making-invalid-states-unrepresentable --openclaw
Files (1)
SKILL.md
4.6 KB

Making Invalid States Unrepresentable

Workflow A: Review Existing Code

  1. Identify the scope (module, file, type, or function under review).
  2. Read the code and enumerate the types, fields, and state representations.
  3. Detect anti-patterns (see checklist below).
  4. For each finding, propose a concrete refactoring using the appropriate technique from references/.
  5. Assess tradeoffs — see references/advanced-topics.md § Tradeoffs.
  6. Present findings as a prioritized list: high-value (core domain, security, APIs) first.

Workflow B: Design New Types

  1. Collect domain requirements: valid states, invalid states, transitions.
  2. Choose modeling techniques — read references/core-and-parse.md for foundational approach.
  3. Model with types: sum types for alternatives, product types for combinations, phantom/branded types for compile-time tags.
  4. Push validation to boundaries: parse external input immediately into precise types.
  5. Validate the design: confirm invalid states cannot be constructed.
  6. Iterate as domain understanding deepens.

Anti-Pattern Detection Checklist

Flag code that exhibits any of these — see references/anti-patterns-and-examples.md for details and fixes:

  • Primitive obsession — raw strings/ints used for domain concepts (IDs, emails, money)
  • Boolean blindness — booleans that lose context about what was verified
  • Optional property proliferation — many optional fields instead of a union type
  • Stringly-typed code — open strings where a closed set of literals applies
  • Shotgun parsing — same validation repeated in multiple call sites
  • Boolean soup — multiple booleans encoding what should be a state machine
  • Unguarded constructors — types with invariants that can be constructed without validation

Technique Selection Guide

SituationTechniqueReference
Mutually exclusive statesSum types / discriminated unionsreferences/techniques-structural.md § 1
Domain-constrained primitivesNewtype + smart constructorreferences/techniques-structural.md § 2
State machine / workflowTypestate patternreferences/techniques-structural.md § 3
Collection must be non-emptyNonEmpty collectionreferences/techniques-structural.md § 4
Prevent argument swapsBranded / opaque typesreferences/techniques-type-level.md § 5
Compile-time state taggingPhantom typesreferences/techniques-type-level.md § 6
Required fields enforcementType-safe builderreferences/techniques-type-level.md § 7
Complex numeric/range invariantsRefinement typesreferences/techniques-type-level.md § 8

Core Principle (Summary)

Design types so invalid states cannot be constructed. Let the compiler enforce correctness. Parse at boundaries, trust types internally. See references/core-and-parse.md.

Output Format

When reviewing code, present each finding as:

  1. Location — file, line, type/function
  2. Anti-pattern — which pattern from the checklist
  3. Risk — what invalid state is possible
  4. Recommendation — specific technique and refactored type signature
  5. Priority — high (core domain/security/API), medium, low

When designing types, present:

  1. Domain states — enumerated valid and invalid states
  2. Type definitions — concrete code in the user's language
  3. Boundary parsers — constructors/factories that validate at entry points
  4. Tradeoff notes — where pragmatism overrides purity

References

  • references/core-and-parse.md — Core principle and parse-don't-validate pattern
  • references/techniques-structural.md — Sum types, newtypes, typestate, NonEmpty
  • references/techniques-type-level.md — Branded types, phantom types, builders, refinement types
  • references/anti-patterns-and-examples.md — Anti-patterns to detect and real-world examples
  • references/implementation-guide.md — Step-by-step process, code review checklist, language support, related principles
  • references/advanced-topics.md — Advanced techniques, modern applications, industry trends, tradeoffs, resources

Source

git clone https://github.com/msewell/agent-stuff/blob/main/skills/making-invalid-states-unrepresentable/SKILL.mdView on GitHub

Overview

This skill guides analyzing code to design type systems that prevent invalid states from being constructible. It centers on techniques like sum types, newtypes, typestate, branded types, and parse-don't-validate, and supports both reviewing code for bugs and designing new domain models.

How This Skill Works

You inspect the codebase to enumerate types and invariants, choose modeling techniques from the reference material, and push validation to boundaries by parsing external input into precise types. The process emphasizes ensuring invalid states cannot be constructed and iterating as domain understanding deepens.

When to Use It

  • Reviewing code for invalid-state bugs and anti-patterns
  • Refactoring types to eliminate impossible states
  • Designing domain models with strict invariants
  • Applying compile-time correctness patterns in new or existing code
  • Language-agnostic guidance to enforce invariants at the type level

Quick Start

  1. Step 1: Identify scope and enumerate domain states and invariants
  2. Step 2: Choose modeling techniques (sum types, newtypes, phantom/branding, typestate) and sketch type definitions
  3. Step 3: Implement boundary parsers and a type-safe builder to enforce invariants at entry points

Best Practices

  • Flag primitive obsession and boolean blindness; prefer closed sets via unions
  • Use sum types over multiple booleans or scattered flags
  • Push validation to boundary parsers and use parse-at-entry
  • Encode state with branded/opaque types and phantom types to prevent mixing
  • Adopt type-safe builders or smart constructors to enforce invariants

Example Use Cases

  • Replace a status field with a discriminated union of Status variants (Pending | Approved | Rejected)
  • Apply typestate to enforce a multi-step workflow (Draft -> Review -> Publish)
  • Wrap IDs and monetary values in newtypes to prevent domain confusion
  • Use phantom types to distinguish compile-time states in a protocol
  • Parse external input at the boundary into precise types instead of validating later

Frequently Asked Questions

Add this skill to your agents

Related Skills

creating-c4-diagrams

msewell/agent-stuff

Creates, reviews, and interprets C4 software architecture diagrams (System Context, Container, Component, Dynamic, Deployment). Produces Structurizr DSL or Mermaid diagram code following C4 model best practices. Use when creating architecture diagrams for a system, reviewing existing C4 diagrams for correctness and anti-patterns, generating Structurizr DSL workspaces, producing Mermaid C4 diagrams for READMEs, or using C4 diagrams as context for design decisions, code generation, risk analysis, or onboarding.

arazzo-specification

msewell/agent-stuff

Guides writing, reviewing, and modifying Arazzo workflow specifications (OpenAPI Initiative standard for multi-step API workflows). Use when creating Arazzo documents from scratch, adding steps or workflows to existing specs, reviewing Arazzo files for correctness, or generating API workflow definitions. Covers document structure, runtime expressions, success criteria, control flow, data threading, reusable components, workflow composition, AI agent integration, and validation.

kotlin-functional-programming

msewell/agent-stuff

Guides writing idiomatic, functional-style Kotlin code using built-in language features. Use when asked to write, review, or refactor Kotlin code for immutability, pure functions, sealed types, error handling, collections, coroutines, or functional architecture patterns.

property-based-testing-with-kotest

msewell/agent-stuff

Writes property-based tests using Kotest's kotest-property module. Identifies testable properties, designs generators, and configures PBT for Kotlin/JVM projects. Use when writing property-based tests, creating custom Arb generators, choosing property patterns (roundtrip, invariant, idempotence, oracle), debugging shrunk counterexamples, or integrating PBT into a Kotlin test suite alongside example-based tests.

reducing-coupling

msewell/agent-stuff

Analyzes a codebase scope for coupling issues, diagnoses coupling types using the Connascence framework, and proposes a comprehensive refactoring plan with concrete code changes. Use when asked to find coupling, reduce dependencies, decouple modules, or improve modularity in a codebase.

mermaid-sequence-diagrams

msewell/agent-stuff

Generates, reviews, and fixes Mermaid sequence diagrams following syntax rules and best practices. Use when creating sequence diagrams from system descriptions, reviewing existing Mermaid sequence diagrams for correctness, fixing parse errors, or refactoring large diagrams into focused sub-diagrams. Covers participants, arrows, activations, control flow, notes, styling, and common anti-patterns.

Sponsor this space

Reach thousands of developers