Skill: alirezarezvani/product-discovery (version 2.1.1)

--- name: product-discovery description: Use when validating product opportunities, mapping assumptions, planning discovery sprints, or testing problem-solution fit before committing delivery resources. --- # Product Discovery Run structured discovery to identify high-value opportunities and de-risk product bets. ## When To Use Use this skill for: - Opportunity Solution Tree facilitation - Assumption mapping and test planning - Problem validation interviews and evidence synthesis - Solution validation with prototypes/experiments - Discovery sprint planning and outputs ## Core Discovery Workflow 1. Define desired outcome - Set one measurable outcome to improve. - Establish baseline and target horizon. 2. Build Opportunity Solution Tree (OST) - Outcome -> opportunities -> solution ideas -> experiments - Keep opportunities grounded in user evidence, not internal opinions. 3. Map assumptions - Identify desirability, viability, feasibility, and usability assumptions. - Score assumptions by risk and certainty. Use: ```bash python3 scripts/assumption_mapper.py assumptions.csv ``` 4. Validate the problem - Conduct interviews and behavior analysis. - Confirm frequency, severity, and willingness to solve. - Reject weak opportunities early. 5. Validate the solution - Prototype before building. - Run concept, usability, and value tests. - Measure behavior, not only stated preference. 6. Plan discovery sprint - 1-2 week cycle with explicit hypotheses - Daily evidence reviews - End with decision: proceed, pivot, or stop ## Opportunity Solution Tree (Teresa Torres) Structure: - Outcome: metric you want to move - Opportunities: unmet customer needs/pains - Solutions: candidate interventions - Experiments: fastest learning actions Quality checks: - At least 3 distinct opportunities before converging. - At least 2 experiments per top opportunity. - Tie every branch to evidence source. ## Assumption Mapping Assumption categories: - Desirability: users want this - Viability: business value exists - Feasibility: team can build/operate it - Usability: users can successfully use it Prioritization rule: - High risk + low certainty assumptions are tested first. ## Problem Validation Techniques - Problem interviews focused on current behavior - Journey friction mapping - Support ticket and sales-call synthesis - Behavioral analytics triangulation Evidence threshold examples: - Same pain repeated across multiple target users - Observable workaround behavior - Measurable cost of current pain ## Solution Validation Techniques - Concept tests (value proposition comprehension) - Prototype usability tests (task success/time-to-complete) - Fake door or concierge tests (demand signal) - Limited beta cohorts (retention/activation signals) ## Discovery Sprint Planning Suggested 10-day structure: - Day 1-2: Outcome + opportunity framing - Day 3-4: Assumption mapping + test design - Day 5-7: Problem and solution tests - Day 8-9: Evidence synthesis + decision options - Day 10: Stakeholder decision review ## Tooling ### `scripts/assumption_mapper.py` CLI utility that: - reads assumptions from CSV or inline input - scores risk/certainty priority - emits prioritized test plan with suggested test types See `references/discovery-frameworks.md` for framework details.

path: references/discovery-frameworks.md
content: # Discovery Frameworks

## Opportunity Solution Tree (OST)

Purpose: continuously connect product outcomes to validated opportunities and tested solutions.

Core structure:
- Outcome (metric)
- Opportunity nodes (needs/pains)
- Solution ideas
- Experiments

OST practice tips:
- Keep tree live; update after each interview or test.
- Separate opportunity evidence from solution proposals.
- Avoid single-branch trees that force one solution.

## Jobs-to-be-Done (JTBD)

Use JTBD to understand progress users seek.

JTBD template:
"When [situation], I want to [motivation], so I can [expected outcome]."

JTBD interview focus:
- Trigger moments
- Current alternatives and workarounds
- Purchase/adoption anxieties
- Desired progress and success criteria

## Kano Model

Classify features by impact on satisfaction:
- Must-be: expected baseline features
- Performance: more is better
- Delighters: unexpected value multipliers
- Indifferent: low impact
- Reverse: can reduce satisfaction for some users

Use Kano when prioritizing solution concepts after problem validation.

## Design Sprint Methodology

Typical phases:
1. Understand
2. Sketch
3. Decide
4. Prototype
5. Test

Discovery usage:
- Compress learning cycle into one week.
- Best for high-ambiguity opportunities requiring cross-functional alignment.

## Assumption Prioritization Matrix

Map assumptions on two axes:
- Risk if wrong (low -> high)
- Certainty (low -> high)

Priority order:
1. High risk, low certainty (test first)
2. High risk, high certainty (validate quickly)
3. Low risk, low certainty (defer)
4. Low risk, high certainty (document)

## Discovery Evidence Rules

- One source is not enough for major decisions.
- Triangulate qualitative and quantitative signals.
- Predefine decision criteria before test execution.
- Archive evidence with date, segment, and method.


path: scripts/assumption_mapper.py
content: #!/usr/bin/env python3
"""Prioritize product assumptions and suggest validation tests."""

import argparse
import csv
from dataclasses import dataclass


@dataclass
class Assumption:
    statement: str
    category: str
    risk: float
    certainty: float

    @property
    def priority_score(self) -> float:
        # High-risk, low-certainty assumptions should be tested first.
        return self.risk * (1.0 - self.certainty)


def parse_float(value: str, field: str) -> float:
    number = float(value)
    if number < 0 or number > 1:
        raise ValueError(f"{field} must be in [0, 1]")
    return number


def suggest_test(category: str) -> str:
    category = category.lower().strip()
    if category == "desirability":
        return "problem interviews or fake-door test"
    if category == "viability":
        return "pricing/willingness-to-pay test"
    if category == "feasibility":
        return "technical spike or architecture prototype"
    if category == "usability":
        return "moderated usability test"
    return "smallest possible experiment with clear success criteria"


def load_from_csv(path: str) -> list[Assumption]:
    assumptions: list[Assumption] = []
    with open(path, "r", encoding="utf-8", newline="") as handle:
        reader = csv.DictReader(handle)
        required = {"assumption", "category", "risk", "certainty"}
        missing = required - set(reader.fieldnames or [])
        if missing:
            missing_str = ", ".join(sorted(missing))
            raise ValueError(f"Missing required columns: {missing_str}")

        for row in reader:
            assumptions.append(
                Assumption(
                    statement=(row.get("assumption") or "").strip(),
                    category=(row.get("category") or "").strip(),
                    risk=parse_float(row.get("risk") or "0", "risk"),
                    certainty=parse_float(row.get("certainty") or "0", "certainty"),
                )
            )
    return assumptions


def parse_inline(items: list[str]) -> list[Assumption]:
    assumptions: list[Assumption] = []
    for item in items:
        # format: statement|category|risk|certainty
        parts = [part.strip() for part in item.split("|")]
        if len(parts) != 4:
            raise ValueError("Inline assumption must be: statement|category|risk|certainty")
        assumptions.append(
            Assumption(
                statement=parts[0],
                category=parts[1],
                risk=parse_float(parts[2], "risk"),
                certainty=parse_float(parts[3], "certainty"),
            )
        )
    return assumptions


def build_parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(description="Prioritize assumptions and generate test plan.")
    parser.add_argument("input", nargs="?", help="CSV file path")
    parser.add_argument(
        "--assumption",
        action="append",
        default=[],
        help="Inline assumption: statement|category|risk|certainty",
    )
    parser.add_argument("--top", type=int, default=10, help="Maximum assumptions to print")
    return parser


def main() -> int:
    parser = build_parser()
    args = parser.parse_args()

    assumptions: list[Assumption] = []
    if args.input:
        assumptions.extend(load_from_csv(args.input))
    if args.assumption:
        assumptions.extend(parse_inline(args.assumption))

    if not assumptions:
        parser.error("Provide a CSV input file or at least one --assumption value.")

    assumptions.sort(key=lambda item: item.priority_score, reverse=True)

    print("prioritized_assumption_test_plan")
    print("rank,priority_score,category,risk,certainty,test,assumption")
    for rank, item in enumerate(assumptions[: args.top], start=1):
        test = suggest_test(item.category)
        print(
            f"{rank},{item.priority_score:.4f},{item.category},{item.risk:.2f},"
            f"{item.certainty:.2f},{test},{item.statement}"
        )

    return 0


if __name__ == "__main__":
    raise SystemExit(main())


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)