Prioritization Frameworks skill for Codex
RICE, WSJF and Kano scores you can defend. Codex chooses the scoring model that fits the list, fixes scales and anchors before scoring, and records evidence for every input so guesses are visible. A bundled Python script ranks a backlog CSV by RICE, ICE or WSJF and flags near-ties, then a sensitivity check halves the shakiest inputs to show which rankings depend on unvalidated assumptions.
curl -fsSL codexskills.dev/install.sh \ | sh -s -- prioritization-frameworks Installs to ~/.agents/skills/prioritization-frameworks/ for every project on this machine.
curl -fsSL codexskills.dev/cli.mjs -o codex-skills.mjsnode codex-skills.mjs install prioritization-frameworks The CLI also searches, updates and removes skills. Run it with no arguments to pick from a list. Needs Node 20.12+.
curl -fsSL codexskills.dev/install.sh \ | sh -s -- --project prioritization-frameworks Installs to .agents/skills/prioritization-frameworks/ in the current repository. Commit it and everyone who runs Codex there gets it.
curl -fsSLO codexskills.dev/downloads/prioritization-frameworks.zipunzip -o prioritization-frameworks.zip -d ~/.agents/skills/ The archive holds the skill folder with its generated agents/openai.yaml. Unzip into .agents/skills/ to scope it to a repo.
& ([scriptblock]::Create((irm codexskills.dev/install.ps1))) prioritization-frameworks PowerShell 5.1 or 7. Installs to %USERPROFILE%\.agents\skills\. Add -Project for the current repo.
104-line POSIX script. No sudo, no telemetry. Read install.sh
Use it in Codex
Start a prompt with $prioritization-frameworks, or pick it from /skills.
You can also just describe the task: Codex reads the description below and loads the playbook when your request matches.
What Codex reads before loading it
Ranks product backlogs and initiative lists with the right scoring model - RICE, ICE, WSJF and cost of delay (CD3), Kano for feature categorization, and MoSCoW for fixed-scope releases - with calibrated scales, evidence for each estimate, sensitivity checks and a bundled script that scores a CSV. Use when asked to prioritize a backlog or feature requests, compare initiatives, run RICE or WSJF scoring, decide what to build next quarter, or explain why one item ranks above another.
Use it when
- A backlog or initiative list needs an ordered, explainable ranking
- Stakeholders disagree on what to build next and want a shared model
- Items have deadlines or decaying value and urgency must be weighed
- You need to separate must-have features from delighters
Use something else when
- You are arranging prioritized themes into horizons over time: use roadmap-planning
- You are sorting a raw inbox of customer feedback first: use feedback-triage
How to check the result
The script runs cleanly, every input cell carries an evidence note or a guess flag, effort came from the team, and the top items survive halving their least certain input.
The mistake it prevents
Adjusting scores until the ranking matches what someone already wanted, instead of recording an explicit override with a reason.
A ranking is done well when each score rests on stated evidence, scales mean the same thing across items, the top of the list survives reasonable changes to uncertain inputs, and the final order is a decision the owner can defend, not a number they hide behind.
Pick the framework
| Situation | Use | Why |
|---|---|---|
| Product backlog, items with measurable reach | RICE | Separates audience size from per-user impact; confidence penalizes guesses |
| Early ideas, growth experiments, little data | ICE | Fast, 1-10 scales; good for weekly experiment triage |
| Items with deadlines, decaying value, or large size differences | WSJF / cost of delay | Rewards urgency and small batch size |
| Deciding which features delight vs are expected | Kano | Categorizes, does not rank; run before scoring |
| Fixed date, must agree scope for one release | MoSCoW | Negotiates scope; useless for ordering a long backlog |
Default to RICE for a typical SaaS backlog. Use one framework per list; mixing scores from different models is meaningless.
RICE
score = Reach x Impact x Confidence / Effort
| Input | Definition | Scale |
|---|---|---|
| Reach | Users or accounts affected per fixed period (e.g. per quarter) | Count from analytics, not a guess when data exists |
| Impact | Effect on the target metric per user reached | 3 massive, 2 high, 1 medium, 0.5 low, 0.25 minimal |
| Confidence | How well evidence supports reach and impact | 100% data-backed, 80% some evidence, 50% gut feel; below 50% means research first |
| Effort | Total person-months (or person-weeks) across all functions | Team estimate, never yours alone |
Fix the time period and effort unit for the whole list before scoring anything.
ICE
score = Impact x Confidence x Ease, each 1-10. Write a one-line anchor for 1, 5 and
10 on each scale before scoring (“Ease 10 = one engineer, under a day”) or scores drift
between items and people.
WSJF and cost of delay
- SAFe-style WSJF:
(business value + time criticality + risk reduction / opportunity enablement) / job size, each scored relative to the other items, usually on a Fibonacci-like scale (1, 2, 3, 5, 8, 13, 20). Score one column at a time across all items, with the smallest item set to 1. - CD3 (cost of delay divided by duration) when money can be estimated: cost of delay in currency per week, duration in weeks. An item losing 20k/week that takes 2 weeks (10k per week of work) beats one losing 50k/week that takes 10 weeks (5k).
- Call out urgency profiles: fixed date (regulatory, event), decaying (competitive window), standard, and intangible (platform health). Fixed-date items with real penalties are scheduled, not scored.
Kano
Classify features with the paired question survey: “How would you feel if the product
had X?” and “…did not have X?”, each answered Like / Expect / Neutral / Tolerate /
Dislike. Map answer pairs to Must-be, Performance, Attractive, Indifferent or Reverse.
Need roughly 20-30 respondents per segment for a stable read. Use the result to make
sure Must-be gaps are fixed first, then score Performance and Attractive items with
RICE. Survey design details: $survey-design.
MoSCoW
For one release with a fixed date. Cap Must at about 60% of the estimated effort so Should and Could absorb overruns. “Won’t (this time)” must be written down and shown to stakeholders.
Workflow
- [ ] 1. Get the list, the goal or metric it should move, and the time horizon
- [ ] 2. Pick the framework (table above); confirm with the user if unclear
- [ ] 3. Fix scales, period and units; write anchors
- [ ] 4. Fill inputs with an evidence note per cell; mark guesses
- [ ] 5. Ask the team for effort/job size; never invent engineering estimates
- [ ] 6. Score with scripts/score_backlog.py
- [ ] 7. Run the sensitivity check; flag ties
- [ ] 8. Write the ranked list with rationale and the decision owner's overrides
Scoring script
scripts/score_backlog.py scores a CSV and prints a ranked table, flags items within
10% of the top score as ties, and validates ranges (RICE impact values, 1-10 ICE scales,
positive effort):
python3 scripts/score_backlog.py backlog.csv --method rice --out ranked.csv
python3 scripts/score_backlog.py experiments.csv --method ice
python3 scripts/score_backlog.py epics.csv --method wsjf
Columns: item,reach,impact,confidence,effort (RICE; confidence as 0-1 or percent),
item,impact,confidence,ease (ICE), or
item,business_value,time_criticality,risk_reduction,job_size (WSJF). Extra columns
such as evidence pass through to the output CSV.
Sensitivity check
For each of the top five items, halve its least-certain input (usually reach or
confidence) and re-score. If the item drops out of the top five, its rank depends on a
guess: label it “rank sensitive - validate X first” and propose the cheapest test
($product-discovery). Items within 10% of each other are ties; break ties on strategy
fit or dependencies, and say so.
Output template
## Prioritized backlog - <scope>, <framework>, period <Q>
Goal: <metric this list should move>
| Rank | Item | Score | Key evidence | Sensitive? |
|---|---|---|---|---|
| 1 | Slack invites | 640 | 1,200 workspaces/qtr hit invite step (funnel) | No |
Ties and judgement calls:
- <item A> vs <item B>: tied; chose A because <reason>
Overrides by owner:
- <item> moved from 6 to 2 because <contract / strategic reason>
Needs evidence before scoring:
- <item>: confidence < 50%; run <test>
Gotchas
- Scores are inputs to a decision, not the decision. Record overrides openly rather than tweaking numbers until the desired order appears.
- Reach inflation: “all users” is rarely true. Use the users who hit the relevant flow.
- Effort from product alone is always low. Include design, QA, data, docs and rollout.
- Re-scoring the same list weekly creates churn. Re-score when evidence changes.
- Bugs, compliance work and incidents bypass the model; schedule them by severity.
- Do not compare RICE scores across teams with different reach units.
Verification
Run the script without errors; confirm every cell has an evidence note or a “guess” mark; confirm effort values came from the team; and confirm the top items survive the sensitivity check or are labelled sensitive. Re-read the final list against the stated goal: if the top item would not move that metric, the inputs or the goal are wrong.
What the zip contains
Codex reads bundled files only when a step points to them. Every one is shown here, so you can review it before installing.
agents/openai.yaml
Gives the Codex app a display name, a one-line description and a starter prompt for this skill.
interface:
display_name: "Prioritization Frameworks"
short_description: "RICE, WSJF and Kano scores you can defend"
default_prompt: "$prioritization-frameworks Score these 25 feature requests with RICE and tell me which rankings are shaky" scripts/score_backlog.py
#!/usr/bin/env python3
"""Score and rank a backlog CSV with RICE, ICE or WSJF.
Usage:
python3 score_backlog.py backlog.csv --method rice [--out ranked.csv]
Required columns per method (header names are case-insensitive):
rice: item, reach, impact, confidence, effort
impact in {0.25, 0.5, 1, 2, 3}; confidence as 0-1 or 0-100 (%)
ice: item, impact, confidence, ease (each 1-10)
wsjf: item, business_value, time_criticality, risk_reduction, job_size
(relative scores, typically Fibonacci 1,2,3,5,8,13,20)
Exits non-zero when columns are missing or values are out of range.
Standard library only.
"""
import argparse
import csv
import sys
METHODS = {
"rice": ["item", "reach", "impact", "confidence", "effort"],
"ice": ["item", "impact", "confidence", "ease"],
"wsjf": ["item", "business_value", "time_criticality", "risk_reduction", "job_size"],
}
RICE_IMPACT = {0.25, 0.5, 1.0, 2.0, 3.0}
def num(row, key, line):
raw = (row.get(key) or "").strip().rstrip("%")
try:
return float(raw)
except ValueError:
raise ValueError(f"line {line}: '{key}' is not a number: {row.get(key)!r}")
def score(method, row, line):
if method == "rice":
reach, impact = num(row, "reach", line), num(row, "impact", line)
conf, effort = num(row, "confidence", line), num(row, "effort", line)
if conf > 1:
conf /= 100.0
if impact not in RICE_IMPACT:
raise ValueError(f"line {line}: impact {impact} not in {sorted(RICE_IMPACT)}")
if not 0 < conf <= 1:
raise ValueError(f"line {line}: confidence must be in (0, 1] or (0, 100]")
if effort <= 0 or reach < 0:
raise ValueError(f"line {line}: effort must be > 0 and reach >= 0")
return reach * impact * conf / effort
if method == "ice":
vals = [num(row, k, line) for k in ("impact", "confidence", "ease")]
if any(not 1 <= v <= 10 for v in vals):
raise ValueError(f"line {line}: ICE values must be 1-10")
return vals[0] * vals[1] * vals[2]
bv, tc, rr = (num(row, k, line) for k in ("business_value", "time_criticality", "risk_reduction"))
size = num(row, "job_size", line)
if size <= 0:
raise ValueError(f"line {line}: job_size must be > 0")
return (bv + tc + rr) / size
def main():
ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
ap.add_argument("csv_path")
ap.add_argument("--method", choices=sorted(METHODS), required=True)
ap.add_argument("--out", help="write ranked CSV with score and rank columns")
args = ap.parse_args()
with open(args.csv_path, newline="", encoding="utf-8-sig") as fh:
reader = csv.DictReader(fh)
if not reader.fieldnames:
sys.exit("error: empty CSV")
reader.fieldnames = [f.strip().lower() for f in reader.fieldnames]
missing = [c for c in METHODS[args.method] if c not in reader.fieldnames]
if missing:
sys.exit(f"error: missing columns for {args.method}: {', '.join(missing)}")
rows, errors = [], []
for line, row in enumerate(reader, start=2):
try:
row["score"] = round(score(args.method, row, line), 2)
rows.append(row)
except ValueError as exc:
errors.append(str(exc))
if errors:
print("\n".join(f"error: {e}" for e in errors), file=sys.stderr)
sys.exit(1)
if not rows:
sys.exit("error: no data rows")
rows.sort(key=lambda r: r["score"], reverse=True)
for i, r in enumerate(rows, start=1):
r["rank"] = i
width = max(len(r["item"]) for r in rows)
print(f"{'rank':>4} {'item':<{width}} score ({args.method})")
for r in rows:
print(f"{r['rank']:>4} {r['item']:<{width}} {r['score']}")
top = rows[0]["score"]
close = [r["item"] for r in rows[1:] if top and abs(top - r["score"]) / top <= 0.10]
if close:
print(f"\nnote: within 10% of the top score: {', '.join(close)} - treat as a tie and decide on judgement")
if args.out:
fields = list(rows[0].keys())
with open(args.out, "w", newline="", encoding="utf-8") as fh:
w = csv.DictWriter(fh, fieldnames=fields)
w.writeheader()
w.writerows(rows)
print(f"\nwrote {args.out}")
if __name__ == "__main__":
main()
About this skill
Written and maintained by the Codex Skills editors to the same editorial standard as every skill here: a selective description, a real workflow, known pitfalls and a way to verify the work. First published , last updated . MIT licensed. Something wrong or out of date? Tell us.