Define the framing of a problem. Change the statement, change the solution space. Use when starting work, when solutions feel wrong, or when you suspect an X-Y problem.
Define the framing. Change the statement, change the solution space.
A problem statement is not the problem itself—it's the lens through which you see the problem. Different framings open different solution spaces. The right framing makes good solutions obvious; the wrong framing makes them invisible.
Invoke /problem-statement when:
/aim but before /solution-space - The natural sequence: aim defines outcome, problem statement frames the challengeDo not use when: You already have a crisp problem statement and are ready to explore solutions. Move to /solution-space.
Before reframing, understand how the problem is currently being seen:
"The problem is currently framed as: [how it's being described]"
Capture:
Watch for the X-Y problem pattern: someone asks for Y (their attempted solution) when they actually need X (the real problem).
Signs of X-Y mismatch:
If X-Y problem detected:
"You're asking for [Y], but the underlying need seems to be [X]. Is that right? If so, we should reframe around [X]."
A good problem statement articulates WHAT needs to change, not HOW to change it.
Wrong: "We need to add a caching layer to reduce latency" Right: "Page loads take 3+ seconds; users abandon before content appears"
Wrong: "We need to refactor the auth module" Right: "Adding a new auth provider takes 2 weeks and touches 6 files"
Test your statement:
Every problem exists within constraints. Name them explicitly:
Hard constraints (actually immovable):
Soft constraints (feel fixed but aren't):
Questions to surface flexibility:
Structure: [Who] needs [what outcome] because [why it matters], but currently [what's blocking].
Good problem statements are:
Examples:
| Bad | Good |
|---|---|
| "The API is slow" | "API responses take 800ms; our SLA requires 200ms" |
| "We need microservices" | "Deploying a fix requires coordinating 4 teams and takes 2 weeks" |
| "Users don't understand the UI" | "40% of support tickets are 'how do I X' where X is a core feature" |
| "We need better tests" | "Last 3 production incidents were caught by users, not tests" |
Before committing to a problem statement, test it:
Produce a problem statement in this structure:
## Problem Statement
**Current framing:** [How the problem is currently being described]
**Reframed as:** [Your crisp problem statement]
**The shift:** [What changed in how we see it]
### Constraints
- **Hard:** [Actually immovable constraints]
- **Soft:** [Constraints that feel fixed but might be flexible]
### What this framing enables
[What solution approaches become visible with this framing]
### What this framing excludes
[What approaches are off the table with this framing—and whether that's intentional]
User asks:
"How do I parse this JSON and extract the user IDs into a separate array?"
X-Y detection:
## Problem Statement
**Current framing:** Need to parse JSON and extract user IDs into an array.
**But wait—why?** This sounds like an attempted solution. What's the underlying need?
**Clarifying questions:**
- What will you do with the array of user IDs?
- Where does this JSON come from?
- How often does this need to happen?
**If the answer is:** "I need to check if the current user is in this list"
**Reframed as:** Need to determine if current user has permission to access this resource.
**The shift:** From data transformation to authorization check. This might be solvable without extracting IDs at all—a simple `includes()` check or a backend permission endpoint.
Original request:
"We need to set up a message queue between services"
Problem statement work:
## Problem Statement
**Current framing:** Set up message queue between services.
**That's a solution. What's the problem?**
After discussion: "When Service A updates, Service B doesn't know about it. Users see stale data."
**Reframed as:** Users see stale data after updates because services don't communicate changes in real-time.
**The shift:** From infrastructure request to user experience problem. Now we can evaluate: Does this need real-time? Is eventual consistency acceptable? Could we solve this with cache invalidation instead?
### Constraints
- **Hard:** Users must see accurate data within 5 seconds of update
- **Soft:** "We use message queues for this" (actually flexible—polling, webhooks, or even a shared cache might work)
### What this framing enables
- Evaluate real-time vs. eventual consistency needs
- Consider polling intervals as a simpler solution
- Question whether these should be separate services at all
### What this framing excludes
- Building complex event-driven architecture before validating the need
Context:
Started as "add a dark mode toggle." Now touching 14 files and we realize there's no theme system.
Problem statement work:
## Problem Statement
**Current framing:** Add dark mode toggle.
**What's actually happening:** We can't add the toggle because there's no theme infrastructure to toggle between.
**Reframed as:** The codebase has no theming system; colors are hardcoded across components.
**The shift:** This is two problems:
1. Build theming infrastructure (larger)
2. Add dark mode as first alternate theme (smaller, depends on #1)
The original ask revealed a missing capability, not a feature to add.
### Constraints
- **Hard:** None identified
- **Soft:** "Ship dark mode this sprint" (may not be realistic given scope)
### What this framing enables
- Properly scope the work (infrastructure then feature)
- Consider: is dark mode the most valuable first use of a theme system?
- Evaluate CSS-in-JS vs. CSS variables vs. other approaches
### What this framing excludes
- Hacking dark mode without addressing the underlying issue (band-aid)
When invoked with a session name (/problem-statement <session>), this skill reads and writes to .oh/<session>.md.
Reading: Check for existing session file. If found, read prior skill outputs—especially the Aim section—for context. The aim informs what problem we're actually trying to solve.
Writing: After producing output, write the problem statement to the session file:
## Problem Statement
**Updated:** <timestamp>
[problem statement content]
If the section exists, replace it. If not, append it after the Aim section.
Works anywhere. Produces problem statement for discussion. No persistence.
.oh/<session>.md for prior context (especially aim).wm/state.md and .wm/dive_context.mdAfter problem statement, typically:
/solution-space - Explore candidate solutions given this framing/problem-space - If you need to map the broader landscape first/aim - If the outcome itself is unclear (go back to clarify)Remember: The problem statement isn't just documentation—it's the leverage point. A different framing doesn't just describe the problem differently; it literally changes what solutions become possible.