software-design-plugin/skills/design-by-contract/SKILL.md
Design with explicit contracts — preconditions, postconditions, invariants, guard clauses. Use when designing a function/class, hardening a boundary, or adding assertions.
npx skillsauth add laurigates/claude-plugins design-by-contractInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
From Code Complete (McConnell) and Meyer's contract model: a routine's correctness is a contract between caller and callee — the caller guarantees the preconditions, the callee guarantees the postconditions, and the object preserves its invariants across every public operation. Making that contract explicit (guard clauses, assertions, documented expectations) is a proactive design technique: it decides where each error is caught and whose responsibility each check is, before the bug exists.
This is the design-time complement to code-quality-plugin:code-hidden-failures,
which detects error-swallowing after the fact. Here the goal is to place the
checks so failures are loud, attributable, and caught at the right layer.
| Use this skill when... | Use something else instead when... |
|---|---|
| Designing a function/class and deciding what it may assume vs must check | Finding existing swallowed errors → code-quality-plugin:code-hidden-failures |
| Hardening a trust boundary (public API, parser, deserialization) | A full correctness/security pass → code-quality-plugin:code-review |
| Deciding where a validation belongs (caller vs callee) | Diagnosing a specific live bug → code-quality-plugin:debugging-methodology |
| Adding assertions/invariants to make assumptions executable | Writing the tests that exercise them → testing-plugin |
| Contract element | Question it answers | Failure if omitted | |---|---|---| | Precondition | What must hold before the routine runs? | Garbage-in produces silent garbage-out | | Postcondition | What does the routine guarantee after? | Callers re-check or assume wrongly | | Invariant | What stays true across every public method? | Object drifts into an impossible state | | Guard clause | Reject the invalid case early, at the top | Deep nesting; the happy path is buried |
Errors vs assertions — the load-bearing distinction. Validate external, expected input (user, network, file, untrusted caller) with real error handling at the boundary; assert internal, impossible conditions (a violated invariant, a precondition another part of your code must have guaranteed) to fail fast in development. Do not validate what an assertion should catch, and never let an assertion guard external input.
Parse $ARGUMENTS:
git diff HEAD +
staged) and say so.Execute this contract design pass:
For the target, list every input and classify it external/expected (validate with error handling) or internal/impossible (assert). State which layer owns each check — push validation outward to the trust boundary so the core can assume clean data.
For each public routine, write its precondition(s), postcondition(s), and — for a
class — the invariant the constructor establishes and every method preserves.
Make them concrete and checkable ("amount > 0 and currency is ISO-4217"),
not vague ("valid input").
Emit per routine: the contract (pre/post/invariant), each check's placement and kind (validate vs assert), and any input currently checked at the wrong layer or not at all. Flag every spot where an external input is only assert-guarded (a production hole) or an internal impossibility is handled as a recoverable error (noise that hides real bugs).
| Mistake | Correct approach |
|---|---|
| Asserting on user/network input | Assertions are for impossible states; validate external input with errors |
| Re-validating clean data in every inner layer | Validate once at the boundary; inner code assumes the contract |
| Vague preconditions ("valid input") | Concrete, checkable conditions |
| Deep if nesting for edge cases | Guard clauses at the top, flat happy path |
| Catching an exception you can't act on | Let it propagate; a swallowed invariant violation hides the bug |
| Input kind | Mechanism | Where | |---|---|---| | External / expected | Error handling + actionable message | Trust boundary | | Internal / impossible | Assertion | Where the invariant must hold | | Invalid early-exit case | Guard clause | Top of the routine | | Class consistency | Invariant established in ctor, preserved per method | Every public method |
code-quality-plugin:code-hidden-failures — detects swallowed errors; this
skill places checks so failures stay loud (design-time complement)code-quality-plugin:code-review — broader correctness/security reviewcode-quality-plugin:debugging-methodology — when a contract was violated and
you're tracing howsoftware-design-plugin:design-deep-modules — a deep module's contract is part
of its small, honest interfacedevelopment
Debug HTTP APIs: trace requests, inspect headers. Use when a request fails: check status first.
documentation
Render architecture diagrams from text sources. Use when documenting system topology.
tools
Inspect JSON payloads and extract nested fields. Use when parsing API responses.
tools
--- name: no-description allowed-tools: Read --- # No Description This skill has no description and must be dropped with a warning.