DmitryDF

opportunity-tree

Opportunity Solution Tree (OST) sub-skill — given a Problem statement, surface a candidate Desired Outcome by decomposing the problem space into opportunities and tracing each back to the operational outcome it implies. KL-primary via Cagan (Inspired ch.7) + Patton (User Story Mapping ch.13); URL-grounded via Teresa Torres OST reference. Called by /clarification Step 1b via opt-in --via-opportunity-tree flag.

DmitryDF 4 Updated 3w ago
GitHub

Install

npx skillscat add dmitrydf/q/opportunity-tree

Install via the SkillsCat registry.

SKILL.md

/opportunity-tree

Given a Problem statement (from /clarification Step 1b), decompose the problem space into 2–5 opportunities and surface a candidate Desired Outcome that, if achieved, would resolve the most load-bearing opportunity branch.

This skill is an AI adapter — "Judgment only, behind a port" (per ~/.claude/rules/code_first_architecture.md §AI Adapter). It receives structured input, returns structured output, and has no state of its own.

The skill does NOT replace /outcome-framing — /outcome-framing reframes an own-words solution into Cagan-shaped outcome wording; /opportunity-tree produces a candidate outcome from a Problem (no solution yet). Both can run; /opportunity-tree is opt-in from Step 1b, /outcome-framing lives at Step 7.


Trigger

Activate when:

  • Called by /clarification Step 1b via the --via-opportunity-tree opt-in flag (the documented calling site)
  • User says /opportunity-tree or "build an opportunity tree" with a Problem statement available

Default OFF in /clarification Step 1b — the user (or /clarification heuristic) opts in.

Main-session use is the default. The skill is pure judgment — no tools required besides Read for KL anchors.


Contract

Input

{
  "problem": "<one-paragraph Problem statement, from /clarification Step 1b>",
  "context": "<optional plain-text context: domain, users, constraints, prior work>"
}

problem is required and non-empty. context may be null.

Output

{
  "tree": {
    "root_outcome_candidate": "<the candidate Desired Outcome at the tree root>",
    "opportunities": [
      {
        "id": "O1",
        "statement": "<one-sentence opportunity — what the team could do to move the outcome>",
        "evidence": "<what makes this opportunity load-bearing — from problem or context>",
        "branch_outcome_trace": "<one sentence — if this opportunity were resolved, what changes for the user>"
      }
    ]
  },
  "desired_outcome_candidate": "<the proposed outcome — operational, observable, no implementation mechanism>",
  "rationale": "<one paragraph — why this outcome dominates the tree, which opportunity branches it resolves, what's deliberately deferred>",
  "next_actions": [
    "Present desired_outcome_candidate to user via AskUserQuestion — (a) accept, (b) revise, (c) reject",
    "On accept: persist as the candidate Desired Outcome that Step 7 will lock",
    "On revise: capture revised text and re-run /outcome-framing for Cagan-shape check",
    "On reject: skill exits; /clarification Step 1b continues without OT contribution"
  ],
  "source_citation": "<KL>/ProductManagement/Sources/Books/inspired-cagan/inspired-cagan.md (Cagan, Inspired ch.7 — outcome vs. output) + <KL>/ProductManagement/Sources/Books/user-story-mapping/user-story-mapping.md (Patton, User Story Mapping ch.13 — opportunity canvas lineage) + https://www.producttalk.org/opportunity-solution-tree/ (Teresa Torres OST canonical reference — URL-grounded for Slice K initial cycle per ~/.claude/rules/plan-gates.md Verification Source Registry)"
}

opportunities has 2–5 rows. desired_outcome_candidate must be operational and observable from the workflow (no models, algorithms, file paths, function names, thresholds).


Execution

Step 1 — Load KL anchors

Read <KL>/ProductManagement/Sources/Books/inspired-cagan/inspired-cagan.md (Cagan ch.7 — outcome vs. output rubric) and <KL>/ProductManagement/Sources/Books/user-story-mapping/user-story-mapping.md (Patton ch.13 — opportunity canvas lineage). These ground the outcome-shape rubric and the opportunity-decomposition pattern.

If KL files unreachable at runtime, proceed and flag in source_citation (Edge Case E5).

Step 2 — Identify the root outcome candidate

From the Problem statement, infer the operational outcome the team would observe if the problem were resolved. Frame it Cagan-shape:

  • Describes the workflow after resolution — what the user (or downstream actor) experiences.
  • Observable from the workflow, not the code.
  • Names no implementation mechanism (no models, algorithms, file paths, thresholds).

This is a candidate; the user accepts/revises/rejects via the calling chain's AskUserQuestion.

Step 3 — Decompose into 2–5 opportunities

Surface 2–5 opportunity branches — each branch is "if the team could move X, the outcome would shift." Each opportunity must:

  • Be evidence-grounded (from problem or context, not invented).
  • Trace cleanly back to the root outcome — if this opportunity were resolved, what changes for the user?
  • Be distinct from siblings — overlapping opportunities collapse to one.

Anti-pattern check: if every opportunity reduces to the same intervention, the tree has only one branch — surface as a single-branch result rather than padding with redundant branches.

Step 4 — Compose rationale + next_actions + return

Write rationale (1 paragraph): why this root outcome dominates the tree, which opportunity branches it resolves, what's deliberately deferred.

Populate next_actions with the four-line standard surface (accept / revise / reject / re-run paths).

Return the JSON object specified in the Output contract.


Edge Cases

# Condition Handling
E1 problem missing or empty Return {"error": "problem required", "tree": null, ...}. Do not invent one.
E2 Problem statement names an implementation mechanism instead of a user-side change Surface in rationale as "input was solution-shaped — outcome candidate strips the mechanism, see /outcome-framing for explicit reframe." Still return a candidate outcome.
E3 Only 1 opportunity inferable (problem is monolithic) Return tree.opportunities with 1 row + flag in rationale: "single-branch tree — opportunity decomposition surfaced no distinct alternatives." Do NOT pad.
E4 More than 5 opportunities inferable Return the top 5 ranked by evidence weight + flag in rationale: "tree pruned to 5 branches; deferred opportunities listed in rationale."
E5 KL or URL source unreachable at runtime Return tree + flag source_citation as "... (UNVERIFIED — file/URL unreachable at runtime)". Do not block.
E6 Candidate outcome contains implementation mechanism Re-draft Step 2 once. If the second draft still leaks mechanism, return the outcome + flag in rationale: "mechanism leak persists — caller should invoke /outcome-framing for explicit reframe."

Source

  • <KL>/ProductManagement/Sources/Books/inspired-cagan/inspired-cagan.md — Cagan, Inspired ch.7 (outcome vs. output rubric)
  • <KL>/ProductManagement/Sources/Books/user-story-mapping/user-story-mapping.md — Patton, User Story Mapping ch.13 (opportunity canvas lineage)
  • https://www.producttalk.org/opportunity-solution-tree/ — Teresa Torres OST canonical reference (URL-grounded for Slice K's initial cycle per ~/.claude/rules/plan-gates.md Verification Source Registry)
  • ~/.claude/rules/code_first_architecture.md — AI adapter / judgment port pattern
  • ~/.claude/rules/plan-gates.md — Verification Source Registry + Gate 0b outcome rubric

Origin attribution. The Opportunity Solution Tree was developed by Teresa Torres (Product Talk) as part of the Continuous Discovery Habits methodology. The Cagan outcome-vs-output frame (ch.7 Inspired) and the Patton opportunity-canvas lineage (ch.13 User Story Mapping) are the KL-primary anchors; Torres' OST is the URL-grounded canonical reference for the tree structure itself.


Sample invocation

Input:

{
  "problem": "When the team plans the next two-week iteration, they cannot defend the resulting plan at the stakeholder review — stakeholders push back on what's included and what's deferred, often forcing a mid-meeting re-prioritization.",
  "context": "Team is 5 engineers + 1 PM; stakeholder review is every other Friday; current process is a flat backlog with no shared rationale recorded per item."
}

Output:

{
  "tree": {
    "root_outcome_candidate": "When the team plans the next iteration, they walk into stakeholder review with a shared plan that survives the meeting without quiet over-commitment or mid-meeting re-prioritization.",
    "opportunities": [
      {
        "id": "O1",
        "statement": "Capture per-item rationale before the review, not during it.",
        "evidence": "Stakeholders push back on what's included — implies the rationale isn't visible to them at review time.",
        "branch_outcome_trace": "Reviewers can read each item's rationale aloud and judge defensibility before re-opening the priority."
      },
      {
        "id": "O2",
        "statement": "Make trade-offs (what's deferred and why) explicit per item.",
        "evidence": "Stakeholders push back on what's deferred — implies the trade-off isn't named.",
        "branch_outcome_trace": "Reviewers see the cost of including any deferred item, and the trade-off becomes the negotiation surface instead of the priority itself."
      },
      {
        "id": "O3",
        "statement": "Anchor the plan in a shared strategy artifact for the period.",
        "evidence": "Mid-meeting re-prioritization suggests the team has no shared anchor to point at.",
        "branch_outcome_trace": "Reviewers see how each item ladders to the period strategy, so the negotiation is against strategy rather than against the team."
      }
    ]
  },
  "desired_outcome_candidate": "When the team plans the next iteration, they walk into stakeholder review with a shared plan that survives the meeting without quiet over-commitment or mid-meeting re-prioritization.",
  "rationale": "The root outcome dominates because all three opportunities ladder back to the same operational change — the team walking out of the review with the original plan intact. O1 (per-item rationale) is load-bearing for defensibility; O2 (trade-off naming) is load-bearing for negotiation honesty; O3 (strategy anchor) is the upstream condition that makes O1 and O2 work. The outcome candidate is observable from the meeting outcome itself — not from any artifact's structure — which is the Cagan-shaped framing.",
  "next_actions": [
    "Present desired_outcome_candidate to user via AskUserQuestion — (a) accept, (b) revise, (c) reject",
    "On accept: persist as the candidate Desired Outcome that Step 7 will lock",
    "On revise: capture revised text and re-run /outcome-framing for Cagan-shape check",
    "On reject: skill exits; /clarification Step 1b continues without OT contribution"
  ],
  "source_citation": "<KL>/ProductManagement/Sources/Books/inspired-cagan/inspired-cagan.md (Cagan, Inspired ch.7 — outcome vs. output) + <KL>/ProductManagement/Sources/Books/user-story-mapping/user-story-mapping.md (Patton, User Story Mapping ch.13 — opportunity canvas lineage) + https://www.producttalk.org/opportunity-solution-tree/ (Teresa Torres OST canonical reference — URL-grounded for Slice K initial cycle per ~/.claude/rules/plan-gates.md Verification Source Registry)"
}

Non-goals

  • This skill does not lock the Desired Outcome — that happens at /clarification Step 9.
  • It does not replace /outcome-framing — OT decomposes the problem space; /outcome-framing reframes an own-words solution into Cagan shape.
  • It does not generate solutions — the tree carries opportunities (problem-side decompositions), not solutions.
  • It does not validate metrics — that is /lean-analytics-metrics at Step 8.
  • It does not fact-check itself. The calling /clarification chain wraps the outcome chain in /double-check at Step 7 and again at Step 9.
  • It does not edit any files. Pure function: input → output.