
Prioritization Frameworks
- 107 installs
- 451 repo stars
- Updated July 21, 2026
- borghei/claude-skills
Rank backlog items with RICE, ICE, MoSCoW, or weighted scoring to narrow MVP scope, roadmap quarters, and stakeholder tradeoffs before committing engineering effort.
About
Prioritization-frameworks helps Claude apply RICE, ICE, MoSCoW, and weighted scoring to rank backlogs, define MVP cuts, document tradeoffs, and align stakeholders before development commitments on SaaS, mobile, and agent products.
- RICE scoring
- ICE quick rank
- MoSCoW buckets
- Weighted matrices
- Stakeholder tradeoff docs
Prioritization Frameworks by the numbers
- 107 all-time installs (skills.sh)
- Ranked #1,334 of 3,282 Productivity & Planning skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/borghei/claude-skills --skill prioritization-frameworksAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 107 |
|---|---|
| repo stars | ★ 451 |
| Last updated | July 21, 2026 |
| Repository | borghei/claude-skills ↗ |
What it does
Rank backlog items with RICE, ICE, MoSCoW, or weighted scoring to narrow MVP scope, roadmap quarters, and stakeholder tradeoffs before committing engineering effort.
Files
Prioritization Framework Expert
Overview
A comprehensive reference to 9 prioritization frameworks with automated scoring, ranking, and guidance on which framework to use in which situation. The core principle: prioritize problems (opportunities), not features. Features are solutions to problems. If you prioritize features directly, you skip the step of understanding whether the problem is worth solving.
When to Use
- Backlog Grooming -- Too many items, need to rank them objectively.
- Quarterly Planning -- Deciding which initiatives to invest in.
- Stakeholder Alignment -- Need a structured way to resolve competing priorities.
- Feature Triage -- Quick sorting of a long list into actionable categories.
Framework Decision Tree
Use this to pick the right framework for your situation:
START: What are you prioritizing?
|
+-- Customer problems/opportunities
| -> Opportunity Score (recommended)
|
+-- Features or initiatives
| |
| +-- Need a quick sort (< 15 items)?
| | -> ICE or Impact vs Effort
| |
| +-- Need rigorous scoring (15+ items)?
| | -> RICE
| |
| +-- Need stakeholder buy-in on criteria?
| | -> Weighted Decision Matrix
| |
| +-- Need to categorize requirements?
| -> MoSCoW
|
+-- Personal PM tasks
| -> Eisenhower Matrix
|
+-- High-uncertainty initiatives
| -> Risk vs Reward
|
+-- Understanding user expectations (not prioritizing)
-> Kano ModelThe 9 Frameworks
1. Opportunity Score (Recommended for Customer Problems)
Source: Dan Olsen, Lean Product Playbook
Formula: Score = Importance x (1 - Satisfaction)
- Importance (0-10): How important is this problem to the customer?
- Satisfaction (0-1): How well do existing solutions satisfy this need? (0 = not at all, 1 = perfectly)
Why it works: It identifies the biggest gaps between what customers need and what they currently have. High importance + low satisfaction = high opportunity.
Example:
| Problem | Importance | Satisfaction | Score |
|---|---|---|---|
| Finding products quickly | 9 | 0.3 | 6.3 |
| Comparing prices | 7 | 0.8 | 1.4 |
| Tracking order status | 8 | 0.6 | 3.2 |
"Finding products quickly" scores highest because it is very important and poorly solved today.
2. ICE -- Impact x Confidence x Ease
Best for: Quick prioritization of a short list (under 15 items).
Formula: Score = Impact x Confidence x Ease
All three scored 1-10:
- Impact: How much will this move the target metric?
- Confidence: How sure are we about the impact estimate?
- Ease: How easy is this to implement? (10 = trivial, 1 = massive effort)
Strengths: Fast, simple, includes uncertainty. Weakness: Subjective. Different people give different scores. Best used as a starting point for discussion, not a final answer.
3. RICE -- (Reach x Impact x Confidence) / Effort
Best for: Rigorous prioritization of a longer list.
Formula: Score = (Reach x Impact x Confidence) / Effort
- Reach: How many users/customers will this affect in a given time period? (number)
- Impact: How much will it affect each user? (3 = massive, 2 = high, 1 = medium, 0.5 = low, 0.25 = minimal)
- Confidence: How sure are we? (100% = high, 80% = medium, 50% = low)
- Effort: Person-months of work required (number)
Strengths: Reach adds a dimension that ICE misses. Effort is estimated in real units, not abstract scores. Weakness: Requires more data (reach estimates, effort sizing).
4. Eisenhower Matrix
Best for: Personal task management for PMs, not product prioritization.
Quadrants:
| Urgent | Not Urgent | |
|---|---|---|
| Important | Do First | Schedule |
| Not Important | Delegate | Eliminate |
- Q1 (Do First): Crisis, deadline-driven. Handle immediately.
- Q2 (Schedule): Strategic work, planning, prevention. This is where PMs should spend most of their time.
- Q3 (Delegate): Interruptions, some meetings, some emails. Hand off if possible.
- Q4 (Eliminate): Time-wasters, unnecessary meetings. Stop doing these.
5. Impact vs Effort (2x2 Matrix)
Best for: Quick visual triage in a group setting.
Quadrants:
| Low Effort | High Effort | |
|---|---|---|
| High Impact | Quick Wins (do first) | Major Projects (plan carefully) |
| Low Impact | Fill-ins (do if time allows) | Money Pits (avoid) |
How to use: Plot items on a whiteboard. Discuss placement. The conversation matters more than the exact position.
6. Risk vs Reward
Best for: Initiatives with significant uncertainty.
Extension of Impact vs Effort that adds an uncertainty dimension:
- Reward = Expected impact if successful
- Risk = Probability of failure x cost of failure
Quadrants:
| Low Risk | High Risk | |
|---|---|---|
| High Reward | Safe Bets (prioritize) | Bold Bets (invest selectively) |
| Low Reward | Incremental (batch) | Avoid |
7. Kano Model
Best for: Understanding customer expectations. Not for prioritization directly.
Categories:
- Must-Be (Basic): Customers expect these. Absence causes dissatisfaction. Presence does not cause delight. (Example: a login page works.)
- One-Dimensional (Performance): More is better, linearly. (Example: faster page loads = happier users.)
- Attractive (Delighters): Unexpected features that create excitement. Absence does not cause dissatisfaction. (Example: automatic dark mode based on system setting.)
- Indifferent: Customers do not care either way.
- Reverse: Some customers actively dislike this feature.
Use Kano to understand, then use another framework (RICE, ICE) to prioritize.
8. Weighted Decision Matrix
Best for: Multi-factor decisions that need stakeholder buy-in.
Process: 1. Define criteria (e.g., customer impact, revenue potential, technical feasibility, strategic alignment). 2. Assign weights to each criterion (must sum to 100%). 3. Score each option against each criterion (1-5 or 1-10). 4. Multiply scores by weights and sum. 5. Rank by total weighted score.
Strengths: Transparent, auditable, gets stakeholders to agree on criteria before scoring. Weakness: Time-consuming. Best for 5-10 high-stakes decisions, not 50-item backlogs.
9. MoSCoW
Best for: Requirements categorization within a fixed scope.
Categories:
- Must Have: Non-negotiable. Without these, the release has no value.
- Should Have: Important but not critical. Painful to leave out but the release still works.
- Could Have: Desirable. Include if time and resources allow.
- Won't Have (this time): Explicitly out of scope. Acknowledged but deferred.
Rule of thumb: Must-Haves should be no more than 60% of the total effort. If everything is a Must-Have, nothing is.
Core Principle: Prioritize Problems, Not Features
Features are solutions. Problems are what matter. Two teams can build different features to solve the same problem. If you prioritize features, you lock in a solution before understanding the problem space.
Workflow: 1. List customer problems (use Opportunity Score to rank them). 2. Pick the top problems to solve. 3. Generate multiple solution ideas for each problem. 4. Prioritize solutions using RICE or ICE. 5. Build the highest-scoring solutions.
This two-step approach (prioritize problems, then prioritize solutions) produces better outcomes than a single pass over a feature list.
Tools
| Tool | Purpose | Command |
|---|---|---|
prioritization_scorer.py | Score and rank items | python scripts/prioritization_scorer.py --input items.json --framework rice |
prioritization_scorer.py | Demo with sample data | python scripts/prioritization_scorer.py --demo --framework rice |
Supported frameworks: rice, ice, opportunity, moscow, weighted
Troubleshooting
| Symptom | Likely Cause | Resolution |
|---|---|---|
| RICE scores dominated by high-reach items regardless of impact | Reach values vary by orders of magnitude, drowning out other factors | Normalize reach to a consistent time window (e.g., users per quarter); consider log-scale for extreme ranges |
| ICE scores feel arbitrary and inconsistent across raters | No calibration on 1-10 scale definitions; different people use different anchors | Define what 1, 5, and 10 mean for each dimension; score independently first, then discuss outliers |
| MoSCoW results in 80% Must-Haves | Team reluctant to deprioritize anything, or no effort constraint applied | Enforce the rule: Must-Haves should be no more than 60% of total effort; make the constraint visible |
| Opportunity Score returns 0 for satisfied needs | Satisfaction scored at 1.0 (fully satisfied), zeroing out the score | Verify satisfaction is on 0-1 scale; values above 1 are auto-converted from 0-10 scale |
| Weighted Decision Matrix produces tied scores | Criteria weights are too evenly distributed, or scoring lacks variance | Increase weight differentiation; force-rank criteria by importance; use the full 1-10 scoring range |
| Framework selection is itself a bottleneck | Team spends time debating which framework to use instead of scoring | Use the Decision Tree in this skill; default to RICE for 15+ items with data, ICE for quick sorts under 15 items |
| Stakeholders disagree with prioritization results | Framework selected does not match stakeholder values, or inputs not transparent | Use Weighted Decision Matrix when multiple stakeholder groups are involved; agree on criteria and weights before scoring |
Success Criteria
- Prioritization framework selected using the Decision Tree, not by habit or preference
- All items scored with consistent definitions for each dimension (documented before scoring begins)
- Results reviewed and discussed as a team, not treated as a mechanical ranking
- Top-priority items have clear next steps (assigned to sprints, PRDs, or experiments)
- Prioritization is repeated at least quarterly, or when significant new information arrives
- The two-step approach is followed: prioritize problems first (Opportunity Score), then prioritize solutions (RICE/ICE)
- MoSCoW Must-Haves never exceed 60% of total effort for a release
Scope & Limitations
In Scope:
- 9 prioritization frameworks with scoring, ranking, and explanation (RICE, ICE, Opportunity Score, Eisenhower, Impact vs. Effort, Risk vs. Reward, Kano, Weighted Decision Matrix, MoSCoW)
- Automated scoring and ranking for RICE, ICE, Opportunity Score, MoSCoW, and Weighted Decision Matrix
- Framework selection guidance via Decision Tree
- Demo data for each framework to illustrate input/output formats
Out of Scope:
- Real-time Jira/Linear backlog integration (manual JSON input required)
- Cost-of-delay or WSJF calculations (see
senior-pm/skill for SAFe portfolio prioritization) - User research to gather importance/satisfaction data for Opportunity Score (see
product-team/skills) - Strategic portfolio allocation decisions (see
senior-pm/skill)
Important Caveats:
- No framework produces a "correct" answer. Prioritization frameworks are decision-support tools that structure conversation, not algorithms that replace judgment.
- RICE and ICE are best for data-rich environments. If your reach and impact estimates are pure guesses, the precision of the formula is misleading.
- The most successful teams combine frameworks: start with Opportunity Score to identify the right problems, then use RICE to rank solutions. Single-framework teams often prioritize solutions to the wrong problems.
- For teams with 50+ people or multiple stakeholder groups, use WSJF or Weighted Decision Matrix with agreed criteria to ensure buy-in.
Integration Points
| Integration | Direction | Description |
|---|---|---|
execution/outcome-roadmap/ | Feeds into | Prioritized items inform Now/Next/Later horizon placement |
execution/create-prd/ | Feeds into | Top-priority items become PRD candidates with P0/P1/P2 feature labels |
execution/brainstorm-okrs/ | Complements | Prioritized initiatives inform which OKR theme to focus on this quarter |
discovery/identify-assumptions/ | Receives from | Assumption risk scores inform item confidence ratings in RICE/ICE |
scrum-master/ | Feeds into | Prioritized backlog items feed sprint planning commitment decisions |
senior-pm/ | Receives from | Portfolio-level WSJF or strategic priorities constrain team-level prioritization |
Tool Reference
prioritization_scorer.py
Scores and ranks items using 5 supported prioritization frameworks. Outputs sorted results with scores, formulas, and category breakdowns.
| Flag | Type | Default | Description |
|---|---|---|---|
--input | string | (required, mutually exclusive with --demo) | Path to JSON file containing items to score |
--demo | flag | off | Run scoring on built-in demo data for the selected framework |
--framework | choice | (required) | Framework to use: rice, ice, opportunity, moscow, weighted |
--format | choice | text | Output format: text or json |
Input JSON schema by framework:
- RICE:
{"items": [{"name": "...", "reach": N, "impact": N, "confidence": N, "effort": N}]} - ICE:
{"items": [{"name": "...", "impact": N, "confidence": N, "ease": N}]} - Opportunity:
{"items": [{"name": "...", "importance": N, "satisfaction": N}]} - MoSCoW:
{"items": [{"name": "...", "category": "must|should|could|wont", "effort": N}]} - Weighted:
{"items": [{"name": "...", "scores": {"criterion": N}}], "criteria": [{"name": "...", "weight": N}]}
References
references/prioritization-guide.md-- Detailed formulas, decision tree, and facilitation tipsassets/prioritization_matrix_template.md-- Scoring templates for each framework
Prioritization Scoring Templates
Templates for each prioritization framework. Copy the relevant section and fill in your data.
---
RICE Scoring Template
Date: [YYYY-MM-DD] Scorer(s): [Names] Context: [What are we prioritizing and why?]
| # | Item | Reach | Impact (0.25-3) | Confidence (%) | Effort (person-months) | RICE Score | Rank |
|---|---|---|---|---|---|---|---|
| 1 | |||||||
| 2 | |||||||
| 3 | |||||||
| 4 | |||||||
| 5 |
Impact Scale: 3 = massive, 2 = high, 1 = medium, 0.5 = low, 0.25 = minimal Confidence Guide: 100% = strong data, 80% = some data, 50% = gut feel Formula: Score = (Reach x Impact x Confidence) / Effort
---
ICE Scoring Template
Date: [YYYY-MM-DD] Scorer(s): [Names]
| # | Item | Impact (1-10) | Confidence (1-10) | Ease (1-10) | ICE Score | Rank |
|---|---|---|---|---|---|---|
| 1 | ||||||
| 2 | ||||||
| 3 | ||||||
| 4 | ||||||
| 5 |
Formula: Score = Impact x Confidence x Ease
---
Opportunity Score Template
Date: [YYYY-MM-DD] Segment: [Who was surveyed?] Sample Size: [N respondents]
| # | Customer Problem | Importance (0-10) | Satisfaction (0-1) | Opportunity Score | Rank |
|---|---|---|---|---|---|
| 1 | |||||
| 2 | |||||
| 3 | |||||
| 4 | |||||
| 5 |
Formula: Score = Importance x (1 - Satisfaction) Threshold: Scores above 6.0 represent strong opportunities.
---
MoSCoW Template
Date: [YYYY-MM-DD] Release: [Version or milestone] Total Effort Budget: [person-weeks or story points]
Must Have (max 60% of effort)
| # | Requirement | Effort | Rationale |
|---|---|---|---|
| 1 | |||
| 2 | |||
| 3 |
Must-Have Effort Total: [sum] | % of Budget: [calculate]
Should Have
| # | Requirement | Effort | Rationale |
|---|---|---|---|
| 1 | |||
| 2 |
Could Have
| # | Requirement | Effort | Rationale |
|---|---|---|---|
| 1 | |||
| 2 |
Won't Have (This Time)
| # | Requirement | Reason for Deferral |
|---|---|---|
| 1 | ||
| 2 |
---
Weighted Decision Matrix Template
Date: [YYYY-MM-DD] Decision: [What are we deciding?] Scorer(s): [Names]
Step 1: Define and Weight Criteria
| Criterion | Weight (sum to 100%) | Description |
|---|---|---|
| [Criterion 1] | % | [What does this measure?] |
| [Criterion 2] | % | |
| [Criterion 3] | % | |
| [Criterion 4] | % | |
| Total | 100% |
Step 2: Score Each Option (1-10)
| Option | [Criterion 1] | [Criterion 2] | [Criterion 3] | [Criterion 4] | Weighted Total | Rank |
|---|---|---|---|---|---|---|
| [Option A] | ||||||
| [Option B] | ||||||
| [Option C] | ||||||
| [Option D] |
Formula: Weighted Total = Sum(score x weight) for all criteria
---
Comparison Table Template
Use this when you want to compare results across frameworks.
| Item | RICE Score | ICE Score | Opportunity Score | MoSCoW Category | Final Priority |
|---|---|---|---|---|---|
---
Decision Log Template
Record prioritization decisions for future reference.
| Date | Decision | Framework Used | Top 3 Items | Rationale | Outcome (fill later) |
|---|---|---|---|---|---|
Example: RICE-Scoring 12 Backlog Items for Q3 (and Comparing to ICE)
Real-world scenario showing how to apply this skill end-to-end.
Context
Acme Analytics is a B2B analytics SaaS, Series B, 80 people. The data platform team owns the ingestion + query engine. Heading into Q3 2026, the team has 12 candidate initiatives competing for ~22 person-months of engineering capacity. The PM (Priya) and engineering lead (Tomas) need a defensible ranking they can defend to the VP of Engineering and the Head of Product without re-litigating every item in the room.
Two pressures collide. First, the CEO has put a "self-serve onboarding" goal on the company OKRs, so anything that lifts activation must be visible in the ranking. Second, several enterprise accounts are escalating a small set of admin-flow bugs. RICE is the right primary framework here (12 items, mixed reach, varying effort), but the team wants an ICE comparison as a sanity check before committing.
Inputs
- 12 candidate items, each with reach (users affected per quarter), impact (RICE 0.25 / 0.5 / 1 / 2 / 3 scale), confidence (50% / 80% / 100%), effort (person-months)
- Q3 capacity: 22 person-months across 6 engineers + 1 designer
- Strategic constraint: at least one activation item must be in the top 5
- Two CRO-escalated bugs that must be assessed objectively, not bumped by politics
Applying the skill
1. Pick the framework. Using the Decision Tree, the team is prioritizing features with 15+ candidates worth of weight on data. RICE wins. ICE is run as a parallel sanity check, not the primary ranking. 2. Define the scoring rubric before scoring. The team writes down what "Impact 2 (High)" means at Acme (lifts a North Star input metric by >=5%), and what Confidence 80% requires (one data point: a customer interview, an A/B test, or an analytics query). This calibration step prevents post-hoc disagreement. 3. Score independently, then converge. Priya and Tomas score every item alone, then meet to reconcile. Items with score deltas of >2x are discussed; everything else takes the average. 4. Run the scorer. Feed the JSON into prioritization_scorer.py. The tool returns ranked output plus rationale. 5. Cross-check with ICE. Re-score the same 12 items in ICE (no reach, just impact x confidence x ease). Compare rank ordering. Where RICE and ICE disagree, dig in -- usually one framework is hiding something. 6. Decide the cutline. Sum effort top-down until 22 person-months is hit. Items above the line go into Q3; items below are explicitly deferred (not lost, not "stretch").
The artifact
Input JSON (RICE)
{
"items": [
{"name": "Self-serve workspace creation", "reach": 4200, "impact": 2, "confidence": 0.8, "effort": 3.0},
{"name": "Query result caching layer", "reach": 3500, "impact": 2, "confidence": 1.0, "effort": 4.0},
{"name": "Admin SSO bug (escalated, Northwind)", "reach": 180, "impact": 3, "confidence": 1.0, "effort": 1.0},
{"name": "Dashboard share link permissions", "reach": 2800, "impact": 1, "confidence": 0.8, "effort": 2.0},
{"name": "Snowflake connector v2", "reach": 1200, "impact": 2, "confidence": 0.8, "effort": 3.5},
{"name": "Mobile read-only viewer", "reach": 5500, "impact": 0.5, "confidence": 0.5, "effort": 5.0},
{"name": "Slack alerting v1", "reach": 2100, "impact": 1, "confidence": 0.8, "effort": 1.5},
{"name": "Audit log export (SOC 2)", "reach": 90, "impact": 3, "confidence": 1.0, "effort": 2.0},
{"name": "Re-onboarding tour for stale users", "reach": 3800, "impact": 1, "confidence": 0.5, "effort": 1.0},
{"name": "BigQuery cost dashboard", "reach": 700, "impact": 2, "confidence": 0.8, "effort": 2.5},
{"name": "Embedded analytics SDK alpha", "reach": 400, "impact": 3, "confidence": 0.5, "effort": 6.0},
{"name": "Admin invite-flow rate limit bug", "reach": 320, "impact": 2, "confidence": 1.0, "effort": 0.5}
]
}Command
python scripts/prioritization_scorer.py --input q3_backlog.json --framework rice --format markdownRICE Output (ranked)
| Rank | Item | Reach | Impact | Conf | Effort | RICE Score |
|---|---|---|---|---|---|---|
| 1 | Admin invite-flow rate limit bug | 320 | 2 | 1.0 | 0.5 | 1280 |
| 2 | Re-onboarding tour for stale users | 3800 | 1 | 0.5 | 1.0 | 1900 |
| 3 | Self-serve workspace creation | 4200 | 2 | 0.8 | 3.0 | 2240 |
| 4 | Query result caching layer | 3500 | 2 | 1.0 | 4.0 | 1750 |
| 5 | Dashboard share link permissions | 2800 | 1 | 0.8 | 2.0 | 1120 |
| 6 | Slack alerting v1 | 2100 | 1 | 0.8 | 1.5 | 1120 |
| 7 | Admin SSO bug (escalated, Northwind) | 180 | 3 | 1.0 | 1.0 | 540 |
| 8 | Audit log export (SOC 2) | 90 | 3 | 1.0 | 2.0 | 135 |
| 9 | Snowflake connector v2 | 1200 | 2 | 0.8 | 3.5 | 548 |
| 10 | BigQuery cost dashboard | 700 | 2 | 0.8 | 2.5 | 448 |
| 11 | Mobile read-only viewer | 5500 | 0.5 | 0.5 | 5.0 | 275 |
| 12 | Embedded analytics SDK alpha | 400 | 3 | 0.5 | 6.0 | 100 |
Note: items are re-sorted by score descending. The "RICE Score" column is `(Reach x Impact x Confidence) / Effort`.
Resorted by score (final ranking)
| Rank | Item | Score | Effort | Cum Effort |
|---|---|---|---|---|
| 1 | Self-serve workspace creation | 2240 | 3.0 | 3.0 |
| 2 | Re-onboarding tour for stale users | 1900 | 1.0 | 4.0 |
| 3 | Query result caching layer | 1750 | 4.0 | 8.0 |
| 4 | Admin invite-flow rate limit bug | 1280 | 0.5 | 8.5 |
| 5 | Dashboard share link permissions | 1120 | 2.0 | 10.5 |
| 6 | Slack alerting v1 | 1120 | 1.5 | 12.0 |
| 7 | Snowflake connector v2 | 548 | 3.5 | 15.5 |
| 8 | Admin SSO bug (escalated, Northwind) | 540 | 1.0 | 16.5 |
| 9 | BigQuery cost dashboard | 448 | 2.5 | 19.0 |
| 10 | Mobile read-only viewer | 275 | 5.0 | 24.0 (over) |
| 11 | Audit log export (SOC 2) | 135 | 2.0 | - |
| 12 | Embedded analytics SDK alpha | 100 | 6.0 | - |
Cutline at 22 person-months: items 1-9 (19.0 PM) make it. Item 10 (Mobile viewer) is 5.0 PM and would put us at 24.0 -- over budget. Defer.
ICE Comparison (same 12 items)
| Item | Impact | Conf | Ease | ICE Score |
|---|---|---|---|---|
| Admin invite-flow rate limit bug | 7 | 10 | 10 | 700 |
| Re-onboarding tour for stale users | 6 | 5 | 9 | 270 |
| Self-serve workspace creation | 9 | 8 | 6 | 432 |
| Query result caching layer | 8 | 10 | 5 | 400 |
| Admin SSO bug (Northwind) | 8 | 10 | 9 | 720 |
| Slack alerting v1 | 5 | 8 | 8 | 320 |
| Audit log export (SOC 2) | 9 | 10 | 7 | 630 |
Disagreement #1: Admin SSO bug ranks #1 by ICE (no reach penalty) but #8 by RICE (only 180 users affected). This is the classic ICE pathology: high-stakes, low-reach items dominate when reach is ignored. RICE is right here -- the bug matters for Northwind, but treating it as the team's top priority would be incorrect.
Disagreement #2: Audit log export ranks #3 by ICE (high impact, high confidence) but #11 by RICE. Same reason -- SOC 2 is critical for some deals, but it does not affect 90% of users in Q3. Decision: pull audit log forward only if Compliance lights up before Q4.
Why this works
- The team did framework selection from the Decision Tree, not by habit. RICE is the right choice for 12 items with usable data.
- Scoring rubrics were defined before scoring. "Impact 2" has a written definition. This removes 80% of late-stage arguments.
- Independent scoring caught two items where Priya and Tomas differed by >2x (Embedded SDK and Mobile Viewer). The discussion surfaced that Tomas was scoring "strategic optionality"; Priya was scoring quarter-impact. They aligned on quarter-impact for RICE and noted the optionality argument separately.
- ICE was used as a sanity check, not the primary ranking. When the two disagree, that disagreement is informative.
- The cutline is explicit and effort-summed. Below-the-line items are deferred on the record, not lost in the backlog.
What's next
- Promote top 9 items into PRD candidates via
../create-prd/. - Push the ranking into Linear as a quarterly project via
../../linear-expert/. - Set up weekly status reporting on the top items via
../status-update-generator/. - Revisit ranking at the mid-quarter check-in described in
../quarterly-planning/. - If new escalations arrive mid-quarter, re-score the affected item only (do not re-rank everything).
Prioritization Frameworks Guide
Detailed reference for each framework with formulas, when to use, common mistakes, and facilitation tips.
---
Framework Formulas
Opportunity Score
Score = Importance x (1 - Satisfaction)- Importance (0-10): Survey customers. Ask: "How important is [problem/need] to you?"
- Satisfaction (0-1): Survey customers. Ask: "How satisfied are you with current solutions for [problem/need]?"
Interpretation: A score above 6 represents a strong opportunity. The highest-scoring problems are both very important and poorly served by current solutions.
ICE
Score = Impact x Confidence x EaseAll on a 1-10 scale:
- Impact: Expected effect on the target metric
- Confidence: How certain you are about the impact estimate
- Ease: How easy to implement (10 = trivial, 1 = very hard)
Score range: 1 to 1,000. Items scoring 500+ are strong candidates.
RICE
Score = (Reach x Impact x Confidence) / Effort- Reach: Number of users/customers affected per quarter (raw number, e.g., 5000)
- Impact: Degree of effect per user (3 = massive, 2 = high, 1 = medium, 0.5 = low, 0.25 = minimal)
- Confidence: Certainty as percentage (100% = high data, 80% = some data, 50% = gut feel)
- Effort: Person-months of work (e.g., 3 = three person-months)
Note: Confidence as a percentage naturally discounts items where you are guessing. A high-impact item with 50% confidence scores half of a high-impact item with 100% confidence.
Weighted Decision Matrix
Score = Sum(criterion_score_i x criterion_weight_i) for all criteriaWeights must sum to 1.0 (or 100%).
MoSCoW
No formula. Categorization only. Rule: Must-Haves should be no more than 60% of total effort.
---
When to Use Each Framework
| Situation | Recommended Framework | Why |
|---|---|---|
| Ranking customer problems | Opportunity Score | Directly measures problem-solution gap |
| Quick triage of small list | ICE | Fast, low overhead, good enough for short lists |
| Rigorous ranking of large backlog | RICE | Reach dimension matters at scale |
| Personal PM task management | Eisenhower Matrix | Urgent/Important is the right lens for tasks |
| Quick visual group exercise | Impact vs Effort | Physical, collaborative, intuitive |
| High-uncertainty initiatives | Risk vs Reward | Accounts for downside, not just upside |
| Understanding expectations | Kano Model | Classifies needs by type, not priority |
| Multi-stakeholder decisions | Weighted Decision Matrix | Transparent, auditable, builds consensus |
| Scoping a release | MoSCoW | Clear categories for requirement negotiation |
---
Common Mistakes Per Framework
Opportunity Score
- Mistake: Using internal estimates instead of customer data for importance and satisfaction.
- Fix: Survey at least 15-20 customers per segment. Internal estimates are biased toward what the team wants to build.
- Mistake: Using demographics to define the segment being surveyed.
- Fix: Define segments by the problem they face, then survey that group.
ICE
- Mistake: Scoring in isolation. One person assigns all scores without discussion.
- Fix: Have 3-5 people score independently, then discuss discrepancies. The discussion reveals hidden assumptions.
- Mistake: All items score 7-8-9 on every dimension (no differentiation).
- Fix: Force-rank first, then score. Or use a wider scale to create separation.
RICE
- Mistake: Inflating reach estimates to game the system.
- Fix: Define reach precisely: "How many users will encounter this feature in Q2?" Use data, not hopes.
- Mistake: Giving everything 100% confidence.
- Fix: Reserve 100% for items with strong data. Use 80% for informed estimates, 50% for guesses.
MoSCoW
- Mistake: Everything is "Must Have."
- Fix: The test: "If we ship without this, does the product have zero value?" If no, it is not a Must Have.
- Mistake: "Won't Have" treated as "never" instead of "not this time."
- Fix: Relabel to "Won't Have This Time" to make deferral explicit and non-permanent.
Weighted Decision Matrix
- Mistake: Choosing criteria after seeing the options (biasing toward a preferred choice).
- Fix: Define and weight criteria before anyone scores any options.
- Mistake: Too many criteria (10+). Dilutes each criterion's influence.
- Fix: Maximum 5-6 criteria. If more seem needed, combine related ones.
---
Combining Frameworks
Frameworks are not mutually exclusive. A common combination:
1. Opportunity Score to rank problems worth solving. 2. RICE to rank solution ideas for the top problems. 3. MoSCoW to scope the first release of the winning solution.
Another combination for team prioritization:
1. Impact vs Effort for a quick visual sort in a group setting. 2. ICE to add rigor to the top quadrant items. 3. Eisenhower for the PM's personal task list afterward.
---
Facilitating Prioritization Sessions
Before the Session
1. Define the decision: What exactly are we prioritizing? (Features? Problems? Initiatives?) 2. Choose the framework: Match to the situation using the decision tree. 3. Prepare the data: List all items. Include brief descriptions. Remove duplicates. 4. Pre-score (optional): Have participants score independently before the session. Discuss discrepancies during the session.
During the Session
1. Align on criteria (5 min): Confirm what the scores mean. What is a 9 vs a 7 for impact? 2. Score independently (10 min): Each participant scores in silence. No groupthink. 3. Reveal and discuss (20 min): Show scores. Focus on items with high variance between scorers. That is where hidden assumptions live. 4. Converge (10 min): Agree on final scores. Use the median, not the average (less susceptible to outliers). 5. Rank and decide (5 min): Sort by score. Confirm the top 3-5 items feel right. If the ranking feels wrong, you missed a criterion.
After the Session
1. Document the scores and the rationale. 2. Share with stakeholders who were not in the room. 3. Revisit in 4-6 weeks to see if priorities changed based on new data.
Facilitation Tips
- Time-box: 60 minutes maximum. Prioritization sessions that run long produce worse decisions, not better ones.
- Separate scoring from debating: Score first, discuss second. If people discuss first, anchoring bias takes over.
- Use a parking lot: Items that spark long debates go on a parking lot list. Score them last, after simpler items calibrate the group.
- The gut check: After scoring, ask: "Does this ranking feel right?" If the top item feels wrong, explore why. Sometimes intuition catches what frameworks miss.
---
Framework Comparison Table
| Framework | Speed | Rigor | Best For | Worst For |
|---|---|---|---|---|
| Opportunity Score | Medium | High | Customer problems | Internal initiatives |
| ICE | Fast | Low | Quick triage | Large backlogs |
| RICE | Medium | High | Feature prioritization | Early-stage ideation |
| Eisenhower | Fast | Low | Personal tasks | Product decisions |
| Impact vs Effort | Fast | Low | Group visual triage | Detailed ranking |
| Risk vs Reward | Medium | Medium | Uncertain bets | Well-understood items |
| Kano | Slow | High | Understanding needs | Ranking priorities |
| Weighted Matrix | Slow | High | Multi-stakeholder | Quick decisions |
| MoSCoW | Fast | Medium | Release scoping | Strategic planning |
Red Flags: Prioritization Frameworks
Common ways this skill's output goes wrong -- concrete examples, why they're bad, and how to fix them.
How to use this document
Scan before sharing a prioritization output (a ranked backlog, a RICE table, an opportunity score). Each red flag has a bad and good quoted example. If your output matches a bad example, fix it before the artifact leaves your machine.
---
Red Flag 1: Everything Scores High Impact
Symptom. Every item in the backlog gets Impact = 3 (massive) on the RICE scale. Why it's bad. RICE is a relative ranking tool. If every item is "massive", you've ranked nothing -- the score collapses to Reach x Confidence / Effort, and Impact loses signal. Worse, leadership starts ignoring impact entirely because it never differentiates. Bad example:
| Item | Reach | Impact | Confidence | Effort | RICE |
| --- | --- | --- | --- | --- | --- |
| Dark mode | 5000 | 3 (massive) | 80% | 2 | 6000 |
| Onboarding redesign | 4000 | 3 (massive) | 70% | 4 | 2100 |
| Tax form export | 800 | 3 (massive) | 90% | 1 | 2160 |
Good example:
| Item | Reach | Impact | Confidence | Effort | RICE |
| --- | --- | --- | --- | --- | --- |
| Dark mode | 5000 | 0.5 (low) | 80% | 2 | 1000 |
| Onboarding redesign | 4000 | 2 (high) | 70% | 4 | 1400 |
| Tax form export | 800 | 3 (massive) | 90% | 1 | 2160 |
How to catch it. Histogram Impact across the backlog. If more than 30% of items score "massive" (3.0), force a recalibration round: only items with documented behavioral or revenue evidence keep the 3.
---
Red Flag 2: Confidence Padding to Hit a Target Rank
Symptom. A favored item's Confidence is bumped from 50% to 80% with no new evidence, just to push it above the cut line. Why it's bad. Confidence is supposed to discount unvalidated ideas. Padding it converts RICE from a calibration tool into a rubber stamp, and the resulting plan systematically over-invests in pet projects. Bad example:
"Marketing wants Item X in the quarter. Bumped Confidence from 50% to 80% so it crosses the line. We will revisit after launch."
Good example:
"Marketing wants Item X. Current Confidence is 50% because we have no usage data. Running a 2-week landing-page test next sprint to gather signal -- if click-through > 4%, Confidence moves to 80% and the item re-enters scoring."
How to catch it. Require a written Confidence Source column. Empty source = Confidence capped at 50%.
---
Red Flag 3: Effort Estimated Without Engineering
Symptom. The PM scored Effort solo, using "small / medium / large" gut feel. Why it's bad. Effort is the only denominator in RICE / ICE. Get it wrong and the entire rank flips. PMs systematically under-estimate backend, security, and migration work because they don't see it. Bad example:
"Effort: 2 person-months. (Set by PM during planning.)"
Good example:
"Effort: 4 person-months. Tech-lead estimate after spike: 2.5 weeks frontend + 3 weeks backend (new event-bus integration) + 1 week QA + 2 weeks security review. Logged in effort-estimates.md."How to catch it. Reject any score where Effort lacks an engineering co-signer.
---
Red Flag 4: Reach Counted as TAM, Not Quarterly Touch
Symptom. Reach = total addressable market (millions) instead of users who will encounter the feature in the next quarter. Why it's bad. RICE's Reach is "people impacted per time unit" (Intercom's original definition was "per quarter"). Using TAM makes every B2C feature dominate every B2B feature, breaking comparability. Bad example:
"Reach: 50,000,000 (all US adults could theoretically use this)."
Good example:
"Reach: 8,400 active users / quarter. Source: MAU report Q1 2026, filtered to users who hit the relevant flow at least once. See reach-source.csv."How to catch it. Reach > 5x your quarterly MAU = wrong unit. Require a data source column.
---
Red Flag 5: ICE for 80-Item Backlogs
Symptom. A 75-item backlog scored with ICE on a 1-10 scale. Why it's bad. ICE is meant for quick triage on small lists (< 15 items). At 75 items the noise dominates -- a 7 and an 8 are statistically indistinguishable but appear adjacent in the rank. Teams treat the order as meaningful and ship low-value work. Bad example:
"Sorted 75 items by ICE. Top 12 go in the quarter."
Good example:
"ICE-triaged 75 items down to top 30 candidates. Re-scored top 30 with RICE using engineering effort estimates. Top 12 by RICE go in the quarter."
How to catch it. Item count > 15 + framework = ICE = re-rank top tertile with RICE.
---
Red Flag 6: MoSCoW with No Must / Should / Could Caps
Symptom. 70% of items are tagged "Must" and 25% are "Should". "Could" and "Won't" are empty. Why it's bad. MoSCoW's value is the forcing function -- a deliverable scope where Musts are roughly 60% of effort, Shoulds 20%, Coulds 20%. Without caps it degenerates into "everything is critical", which is just a flat list. Bad example:
"Must: 23 items. Should: 8 items. Could: 0. Won't: 0."
Good example:
"Must: 8 items (~55% of capacity). Should: 5 items (~25%). Could: 6 items (~20%, drop if Musts slip). Won't (this release): 14 items, documented in wont-this-release.md."How to catch it. Must >= 75% of items = MoSCoW abuse. Re-run with explicit capacity caps.
---
Red Flag 7: Opportunity Score Sourced from a 12-Person Survey
Symptom. Opportunity scores (Importance + Unsatisfaction) calculated from a 12-respondent internal survey. Why it's bad. Ulwick's Outcome-Driven Innovation requires n >= 180 to separate signal from noise (and ideally 300+ across segments). Twelve responses produce wide confidence intervals and the rank can be reshuffled by 2-3 respondents changing minds. Bad example:
"Opportunity score for 'reduce time to first invoice' = 14.2. (n = 12 internal pilot users.)"
Good example:
"Opportunity score for 'reduce time to first invoice' = 14.2 (95% CI: 12.8 - 15.6). n = 247 customers, segmented by ARR band and persona. Survey instrument and raw data in odi-q1-2026/."How to catch it. Any opportunity score without n, segmentation, and confidence interval should be marked draft and not used for prioritization.
---
Red Flag 8: WSJF Without Job-Size Calibration
Symptom. WSJF (Cost of Delay / Job Size) used on a team that has never calibrated story points. Why it's bad. WSJF amplifies the denominator. If Job Size estimates are noisy (which they always are in an uncalibrated team), the rank is dominated by whoever shouted "small!" loudest, not by actual value-per-effort. Bad example:
"Item A: CoD = 80, Size = 1, WSJF = 80. Item B: CoD = 200, Size = 5, WSJF = 40. Ship A first."
Good example:
"Item A: CoD = 80, Size = 1 (calibrated against 6 reference stories from last quarter; 80% confidence). Item B: CoD = 200, Size = 5 (same calibration). WSJF still favors A, but flagged for review because Item B has a hard deadline -- moving to CD3 framework instead."
How to catch it. No reference-story calibration = WSJF is not the right framework. Use Impact x Effort 2x2 instead.
---
Red Flag 9: Kano Model Without Recent User Research
Symptom. Features classified as Delighter / Performance / Must-Have based on PM intuition, not Kano survey data. Why it's bad. Kano categories shift over time -- yesterday's Delighter is today's Must-Have (think: search bar, dark mode, single-sign-on). Classifying from intuition produces a snapshot of the PM's mental model, not the market's. Bad example:
"Two-factor auth: Delighter. Users will love that we offer it."
Good example:
"Two-factor auth: Must-Have for enterprise segment, Performance for SMB. Source: Kano survey Q4 2025 (n=412, both functional + dysfunctional questions). 78% of enterprise respondents in 'I expect it' band; SMB split 45 / 40."
How to catch it. Kano classification without a survey reference is fan-fiction.
---
Red Flag 10: No Tie-Breaker Rule for Identical Scores
Symptom. Three items tied at RICE = 1400, no documented rule for picking which goes first. Why it's bad. Ties get resolved by hallway politics. The most senior voice picks the winner, and the prioritization process loses credibility ("they were going to pick that one anyway"). Bad example:
"Items A, B, C all scored 1400. Picked A because it was easiest to start."
Good example:
"Items A, B, C all scored 1400. Tie-breaker rule (from prioritization-charter.md): strategic theme alignment first, then customer commitments, then team dependencies. A and B align to 'Activation' theme; B has a Q1 customer commitment. Picked B."How to catch it. Identical scores without a documented tie-breaker = bring the charter, not the loudest voice.
---
Red Flag 11: Mixing Frameworks Without Explanation
Symptom. Backlog spreadsheet has RICE for half the items, ICE for others, and MoSCoW tags on the rest -- combined into a single rank. Why it's bad. Different frameworks produce different score distributions. Mixing them is like ranking athletes by combining marathon times with weightlifting kilos. The result looks rigorous but is meaningless. Bad example:
"Top of the backlog: RICE = 2400. Next item: ICE = 9. Next: MoSCoW = Must. Sorted by 'priority score'."
Good example:
"Backlog split into three buckets: opportunities (ranked by Opportunity Score, n=247), features (ranked by RICE), and constraints (ranked by MoSCoW). Quarterly slate pulls top items from each bucket according to capacity rules in prioritization-charter.md."How to catch it. A single sort column that mixes framework outputs is always wrong.
---
Red Flag Quick Reference
| # | Anti-pattern | One-line check |
|---|---|---|
| 1 | Everything is Impact = massive | Histogram Impact; >30% massive triggers recalibration |
| 2 | Confidence padding | Require a Confidence Source column |
| 3 | Effort estimated solo | Reject scores without engineering co-signer |
| 4 | Reach = TAM | Reach > 5x quarterly MAU = wrong unit |
| 5 | ICE for big backlogs | >15 items + ICE = re-rank top tertile with RICE |
| 6 | MoSCoW with no caps | Must >= 75% of items = abuse |
| 7 | Opportunity score, n=12 | Require n, segmentation, confidence interval |
| 8 | WSJF, no calibration | No reference-story calibration = use 2x2 instead |
| 9 | Kano from intuition | No survey reference = fan-fiction |
| 10 | Ties resolved by politics | Document a tie-breaker rule in charter |
| 11 | Mixed framework rank | Single sort column mixing outputs = always wrong |
Related Reading
SKILL.md-- framework decision tree (which framework when)references/frameworks.md-- the 9 frameworks with worked examplesscripts/prioritization_scorer.py --help-- the scoring tool- Sibling skill:
execution/backlog-refinement/-- INVEST / DoR / DoD - Sibling skill:
discovery/identify-assumptions/-- before scoring, validate the assumption
#!/usr/bin/env python3
"""Prioritization Scorer - Score and rank items using multiple prioritization frameworks.
Supports RICE, ICE, Opportunity Score, MoSCoW, and Weighted Decision Matrix.
Calculates scores, ranks items, and outputs sorted results with explanations.
Usage:
python prioritization_scorer.py --input items.json --framework rice
python prioritization_scorer.py --demo --framework ice
python prioritization_scorer.py --demo --framework opportunity
python prioritization_scorer.py --demo --framework moscow
python prioritization_scorer.py --demo --framework weighted
python prioritization_scorer.py --demo --framework rice --format json
Input JSON formats vary by framework. Use --demo to see examples.
Standard library only. No external dependencies.
"""
import argparse
import json
import sys
import textwrap
# ============================================================
# Framework Implementations
# ============================================================
def score_rice(items: list[dict]) -> list[dict]:
"""Score items using RICE: (Reach * Impact * Confidence) / Effort."""
results = []
for item in items:
name = item.get("name", "Untitled")
reach = item.get("reach", 0)
impact = item.get("impact", 0)
confidence = item.get("confidence", 0)
effort = item.get("effort", 1)
if effort <= 0:
effort = 1 # Avoid division by zero
# Confidence should be 0-1 range; accept 0-100 and convert
if confidence > 1:
confidence = confidence / 100.0
score = (reach * impact * confidence) / effort
results.append({
"name": name,
"score": round(score, 2),
"details": {
"reach": reach,
"impact": impact,
"confidence": confidence,
"effort": effort,
},
"formula": f"({reach} * {impact} * {confidence:.2f}) / {effort} = {score:.2f}",
})
results.sort(key=lambda x: x["score"], reverse=True)
return results
def score_ice(items: list[dict]) -> list[dict]:
"""Score items using ICE: Impact * Confidence * Ease."""
results = []
for item in items:
name = item.get("name", "Untitled")
impact = item.get("impact", 0)
confidence = item.get("confidence", 0)
ease = item.get("ease", 0)
score = impact * confidence * ease
results.append({
"name": name,
"score": round(score, 2),
"details": {
"impact": impact,
"confidence": confidence,
"ease": ease,
},
"formula": f"{impact} * {confidence} * {ease} = {score:.2f}",
})
results.sort(key=lambda x: x["score"], reverse=True)
return results
def score_opportunity(items: list[dict]) -> list[dict]:
"""Score items using Opportunity Score: Importance * (1 - Satisfaction)."""
results = []
for item in items:
name = item.get("name", "Untitled")
importance = item.get("importance", 0)
satisfaction = item.get("satisfaction", 0)
# Clamp satisfaction to 0-1 range
if satisfaction > 1:
satisfaction = satisfaction / 10.0 # Accept 0-10 scale
satisfaction = max(0, min(1, satisfaction))
score = importance * (1 - satisfaction)
results.append({
"name": name,
"score": round(score, 2),
"details": {
"importance": importance,
"satisfaction": satisfaction,
"gap": round(1 - satisfaction, 2),
},
"formula": f"{importance} * (1 - {satisfaction:.2f}) = {score:.2f}",
})
results.sort(key=lambda x: x["score"], reverse=True)
return results
def score_moscow(items: list[dict]) -> list[dict]:
"""Categorize and sort items using MoSCoW."""
category_order = {"must": 0, "should": 1, "could": 2, "wont": 3}
category_labels = {"must": "Must Have", "should": "Should Have", "could": "Could Have", "wont": "Won't Have"}
results = []
for item in items:
name = item.get("name", "Untitled")
category = item.get("category", "could").lower().replace("'", "").replace(" ", "")
# Normalize category names
if category.startswith("must"):
category = "must"
elif category.startswith("should"):
category = "should"
elif category.startswith("could"):
category = "could"
else:
category = "wont"
effort = item.get("effort", None)
order = category_order.get(category, 3)
results.append({
"name": name,
"category": category_labels.get(category, category),
"sort_order": order,
"effort": effort,
"details": {
"category": category,
"effort": effort,
},
})
results.sort(key=lambda x: (x["sort_order"], -(x["effort"] or 0)))
return results
def score_weighted(items: list[dict], criteria: list[dict] | None = None) -> list[dict]:
"""Score items using Weighted Decision Matrix.
Each item must have a 'scores' dict mapping criterion name to score (1-10).
Criteria list provides name and weight for each criterion.
"""
if not criteria:
criteria = [
{"name": "customer_impact", "weight": 0.3},
{"name": "revenue_potential", "weight": 0.25},
{"name": "feasibility", "weight": 0.25},
{"name": "strategic_alignment", "weight": 0.2},
]
# Normalize weights
total_weight = sum(c["weight"] for c in criteria)
if total_weight > 0:
for c in criteria:
c["weight"] = c["weight"] / total_weight
results = []
for item in items:
name = item.get("name", "Untitled")
scores = item.get("scores", {})
weighted_total = 0
score_breakdown = {}
for c in criteria:
cname = c["name"]
raw_score = scores.get(cname, 0)
weighted_score = raw_score * c["weight"]
weighted_total += weighted_score
score_breakdown[cname] = {
"raw": raw_score,
"weight": round(c["weight"], 2),
"weighted": round(weighted_score, 2),
}
results.append({
"name": name,
"score": round(weighted_total, 2),
"details": score_breakdown,
})
results.sort(key=lambda x: x["score"], reverse=True)
return results
# ============================================================
# Demo Data
# ============================================================
DEMO_DATA = {
"rice": {
"items": [
{"name": "Advanced search", "reach": 5000, "impact": 2, "confidence": 80, "effort": 3},
{"name": "Mobile app", "reach": 8000, "impact": 3, "confidence": 50, "effort": 8},
{"name": "SSO integration", "reach": 1200, "impact": 2, "confidence": 90, "effort": 2},
{"name": "Dashboard redesign", "reach": 6000, "impact": 1, "confidence": 70, "effort": 4},
{"name": "API rate limiting", "reach": 300, "impact": 3, "confidence": 95, "effort": 1},
],
},
"ice": {
"items": [
{"name": "Advanced search", "impact": 8, "confidence": 7, "ease": 5},
{"name": "Mobile app", "impact": 9, "confidence": 5, "ease": 3},
{"name": "SSO integration", "impact": 6, "confidence": 9, "ease": 7},
{"name": "Dashboard redesign", "impact": 5, "confidence": 6, "ease": 6},
{"name": "API rate limiting", "impact": 7, "confidence": 9, "ease": 8},
],
},
"opportunity": {
"items": [
{"name": "Finding products quickly", "importance": 9, "satisfaction": 0.3},
{"name": "Comparing prices", "importance": 7, "satisfaction": 0.8},
{"name": "Tracking order status", "importance": 8, "satisfaction": 0.6},
{"name": "Managing returns", "importance": 6, "satisfaction": 0.4},
{"name": "Saving favorites", "importance": 5, "satisfaction": 0.7},
],
},
"moscow": {
"items": [
{"name": "User authentication", "category": "must", "effort": 3},
{"name": "Data export", "category": "should", "effort": 2},
{"name": "Dark mode", "category": "could", "effort": 1},
{"name": "Payment processing", "category": "must", "effort": 5},
{"name": "Social login", "category": "could", "effort": 2},
{"name": "Blockchain integration", "category": "wont", "effort": 8},
{"name": "Search functionality", "category": "must", "effort": 4},
{"name": "Email notifications", "category": "should", "effort": 2},
],
},
"weighted": {
"items": [
{
"name": "Advanced search",
"scores": {"customer_impact": 9, "revenue_potential": 7, "feasibility": 6, "strategic_alignment": 8},
},
{
"name": "Mobile app",
"scores": {"customer_impact": 8, "revenue_potential": 9, "feasibility": 4, "strategic_alignment": 7},
},
{
"name": "SSO integration",
"scores": {"customer_impact": 5, "revenue_potential": 8, "feasibility": 8, "strategic_alignment": 6},
},
{
"name": "Dashboard redesign",
"scores": {"customer_impact": 7, "revenue_potential": 4, "feasibility": 7, "strategic_alignment": 5},
},
],
"criteria": [
{"name": "customer_impact", "weight": 0.3},
{"name": "revenue_potential", "weight": 0.25},
{"name": "feasibility", "weight": 0.25},
{"name": "strategic_alignment", "weight": 0.2},
],
},
}
# ============================================================
# Formatting
# ============================================================
def format_text_report(results: list[dict], framework: str) -> str:
"""Format results as human-readable text."""
lines = []
lines.append("=" * 60)
lines.append(f"PRIORITIZATION REPORT -- {framework.upper()}")
lines.append("=" * 60)
lines.append("")
if framework == "moscow":
current_category = None
for i, r in enumerate(results, 1):
if r["category"] != current_category:
current_category = r["category"]
lines.append(f" [{current_category}]")
effort_str = f" (effort: {r['effort']})" if r.get("effort") is not None else ""
lines.append(f" {i}. {r['name']}{effort_str}")
lines.append("")
# Summary
categories = {}
total_effort = 0
for r in results:
cat = r["category"]
categories[cat] = categories.get(cat, 0) + 1
if r.get("effort") is not None:
total_effort += r["effort"]
lines.append(" Summary:")
for cat, count in categories.items():
lines.append(f" {cat}: {count} items")
lines.append(f" Total effort: {total_effort}")
must_effort = sum(r.get("effort", 0) or 0 for r in results if r.get("category") == "Must Have")
if total_effort > 0:
must_pct = (must_effort / total_effort) * 100
lines.append(f" Must-Have effort: {must_pct:.0f}% of total", )
if must_pct > 60:
lines.append(" [WARN] Must-Haves exceed 60% of effort. Consider reclassifying.")
else:
for i, r in enumerate(results, 1):
lines.append(f" {i}. {r['name']}")
lines.append(f" Score: {r['score']}")
if "formula" in r:
lines.append(f" Formula: {r['formula']}")
if "details" in r and framework == "weighted":
for crit, vals in r["details"].items():
lines.append(f" {crit}: {vals['raw']} x {vals['weight']} = {vals['weighted']}")
lines.append("")
lines.append("=" * 60)
lines.append(f"Items ranked: {len(results)}")
lines.append(f"Framework: {framework.upper()}")
lines.append("=" * 60)
return "\n".join(lines)
# ============================================================
# CLI
# ============================================================
SUPPORTED_FRAMEWORKS = ["rice", "ice", "opportunity", "moscow", "weighted"]
def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
"""Parse command-line arguments."""
parser = argparse.ArgumentParser(
description="Score and rank items using prioritization frameworks.",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=textwrap.dedent("""\
Supported frameworks:
rice (Reach * Impact * Confidence) / Effort
ice Impact * Confidence * Ease
opportunity Importance * (1 - Satisfaction)
moscow Must/Should/Could/Won't categorization
weighted Weighted Decision Matrix with custom criteria
Examples:
python prioritization_scorer.py --demo --framework rice
python prioritization_scorer.py --demo --framework opportunity --format json
python prioritization_scorer.py --input items.json --framework ice
"""),
)
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument(
"--input",
help="Path to JSON file containing items to score",
)
group.add_argument(
"--demo",
action="store_true",
help="Run scoring on built-in demo data for the selected framework",
)
parser.add_argument(
"--framework",
required=True,
choices=SUPPORTED_FRAMEWORKS,
help="Prioritization framework to use",
)
parser.add_argument(
"--format",
choices=["text", "json"],
default="text",
help="Output format: text (default) or json",
)
return parser.parse_args(argv)
def main(argv: list[str] | None = None) -> None:
"""Main entry point."""
args = parse_args(argv)
if args.demo:
data = DEMO_DATA.get(args.framework, {})
else:
try:
with open(args.input, "r", encoding="utf-8") as f:
data = json.load(f)
except FileNotFoundError:
print(f"Error: File not found: {args.input}", file=sys.stderr)
sys.exit(1)
except json.JSONDecodeError as e:
print(f"Error: Invalid JSON in {args.input}: {e}", file=sys.stderr)
sys.exit(1)
items = data.get("items", [])
if not items:
print("Error: No items found in input data.", file=sys.stderr)
sys.exit(1)
# Route to framework
if args.framework == "rice":
results = score_rice(items)
elif args.framework == "ice":
results = score_ice(items)
elif args.framework == "opportunity":
results = score_opportunity(items)
elif args.framework == "moscow":
results = score_moscow(items)
elif args.framework == "weighted":
criteria = data.get("criteria", None)
results = score_weighted(items, criteria)
else:
print(f"Error: Unknown framework: {args.framework}", file=sys.stderr)
sys.exit(1)
if args.format == "json":
print(json.dumps(results, indent=2))
else:
print(format_text_report(results, args.framework))
if __name__ == "__main__":
main()