name: stress-test
description: Stress-test an interface or system design by walking it through usage scenarios, finding gaps, and refining across cycles. Use when the user wants to validate a design, test a public interface against real usage, find design gaps, mentions "design stress test", "scenario walkthrough", "stress test the design", "interface validation", "design review", or when /spec-plan or /codebase-design needs design validation.
Stress Test
Stress-test a design by walking it through scenarios — concrete usage narratives that expose gaps, inconsistencies, and complications the design misses when described abstractly. Run 2 cycles of scenario → find → refine. If the second cycle still reveals structural weaknesses, run a third.
Uses /domain-modeling to pin down the ubiquitous language in every scenario, and /codebase-design to judge interfaces for depth, seam placement, and leverage.
Scenario groups
Three groups, run in order:
- Normal usage — each happy-path traversal, exercised in ≥3 ways. Start simple (one caller, one outcome) and escalate to complex (multiple callers, concurrent paths, evolving state).
- Edge cases — each boundary traversal, exercised in ≥3 ways: invalid inputs (different shapes of invalidity), resource exhaustion (different resources depleted), partial failure (different points of failure), race conditions (different interleavings), empty/null states (different sources of emptiness), forbidden transitions (different ways to attempt them).
- Stretch scenarios — scenarios outside the documented scope that stretch the design past its intended limits, exposing where it breaks and what improvements are one step away. Exercised in ≥3 ways: composition stretch (pair with modules it wasn't designed alongside), domain stretch (apply the same interface shape to a neighboring domain), scale stretch (reverse a core scale assumption — the fast path becomes the bottleneck), extension stretch (attempt a capability one step beyond current scope with minimal adaptation), architectural stretch (place in a different architectural style — event-driven, embedded, synchronous where it was async).
What a good scenario is
A scenario is a short, concrete narrative:
- Who — which caller or actor
- Calls what — which interface entry point
- With what — specific inputs, not ranges
- In what state — preconditions on the system
- Expecting what — observable outcome
Vague: "A user places an order." Concrete: "A Customer calls placeOrder with 3 line items and a valid shipping address, while one item is low-stock; expects an OrderConfirmed event with an allocated inventory reservation."
Stretch: "An analytics pipeline tries to compose the module with a streaming processor — a pairing the design never anticipated; expects to discover whether the interface can serve that role or what minimal change would unlock it."
Cycle 1 — First walkthrough
Step 1: Load the world
Load /domain-modeling. Read CONTEXT.md for the ubiquitous language.
Load /codebase-design. Identify:
- Every module and its interface — the full surface a caller sees
- Every seam — where interfaces live
- Every adapter — what satisfies each interface
- Dependency categories: in-process, local-substitutable, remote, external
Completion: every module and its seam identified, every adapter mapped, dependencies classified.
Step 2: Map paths and generate scenarios
First, enumerate every distinct path through the interface — a path is any distinct traversal: a method call, a conditional branch, a state transition, an error mode, an adapter dispatch.
If the path count explodes, halt. Path explosion means shallow design. Simplify by merging equivalent paths into fewer, deeper entry points, or split the module at a new seam so each half carries a smaller surface. Only resume once the path map is tractable.
Once the path map is tractable, generate ≥3 scenarios per path. Vary at least one axis per scenario:
- Different input values
- Different caller context (who is calling, their state)
- Different preconditions (system state before the call)
- Different concurrency (single caller vs. overlapping calls)
Organize: normal-usage first, then edge cases, then stretch scenarios, simple→complex within each.
For stretch scenarios, instead of path enumeration, map adjacent territories — every neighboring domain, every plausible composition, every scale assumption, and every extension point one step beyond the current surface. Generate ≥3 scenarios per territory.
Completion: every path covered, each tested ≥3 ways, no path explosion left unresolved.
Step 3: Walk each scenario through the design
For each scenario, write out the full call sequence through the interfaces. At every interface touch, ask:
- Information — does the interface carry enough for the caller to proceed? Or does the caller need knowledge the interface should hide?
- Depth — is the interface forcing shallow pass-through, where the caller does the real work?
- Domain language — does the domain language stay consistent under this usage? Run
/domain-modelingto challenge every term that conflicts withCONTEXT.md. - Seam placement — is the cut in the right place? Apply the deletion test: if this module vanished, would complexity reappear across callers?
Completion: every scenario walked, every interface touch examined against all four questions.
Step 4: Record findings
Produce a findings list. One finding per gap, inconsistency, or complication. Each finding names:
- The affected module and interface
- The scenario that exposed it
- The specific issue
Completion: all gaps, inconsistencies, and complications recorded, one per finding.
Step 5: Refine
Feed findings back into the design. For each finding, propose a concrete change using /codebase-design vocabulary:
- Re-shape an interface (reduce surface, simplify parameters)
- Relocate a seam (move the cut to where behavior concentrates)
- Split or merge modules
- Sharpen a domain term via
/domain-modeling
Completion: every finding addressed with a concrete change proposal.
Cycle 2 — Refined walkthrough
Step 6: Re-walk the same scenarios
Walk every scenario from Step 2 against the refined design. Two checks:
- No regressions — every scenario must still succeed
- Simpler expression — each scenario touch fewer interfaces, demand less caller-side knowledge, use clearer domain language than in Cycle 1
Completion: all scenarios re-walked, regressions caught, simplicity compared against Cycle 1.
Step 7: Record remaining findings
Document the gaps that survived both cycles — issues the second refinement still hasn't closed.
Completion: survivors documented.
Step 8: Recommend
Present to the user:
- Clear wins — refinements that measurably improved depth, locality, or domain clarity
- Trade-offs — refinements that helped one axis but cost another
- Unresolved — findings that need design work beyond the skill's scope
If unresolved findings are structural, offer a third cycle focused on those.
Completion: recommendation delivered to user.
Rules
- Scenarios are concrete. "A Customer calls
placeOrderwith 3 line items" — not "the ordering flow." Vague scenarios produce vague findings. - One finding per issue. Don't bundle multiple problems into one finding.
- Refine the design, never the scenarios. If a scenario exposes a weakness, fix the design. Don't water down the scenario to make the design look good.
- Minimum 2 cycles. The second cycle is where regressions surface and real depth emerges.
- Path explosion means shallow design. If enumerating paths produces a combinatorial explosion, the interface is the defect. Simplify or split, then resume — don't paper over it with fewer scenarios.