
Wwas
- 83 installs
- 451 repo stars
- Updated July 21, 2026
- borghei/claude-skills
wwas is a Claude skill that writes backlog items in a Why-What-Acceptance format connecting each item to strategic business objectives.
About
WWAS creates backlog items in a Why-What-Acceptance format that ties every work item to strategic business objectives. The Why gives strategic context, the What is a concise reminder of the discussion, and the acceptance criteria are observable outcomes. Product teams use it during backlog creation, sprint planning, and roadmap decomposition, gated by INVEST criteria.
- Why-What-Acceptance backlog format connecting each item to strategic objectives
- Enforces single-owner strategic Why plus 4+ observable acceptance criteria
- INVEST quality gates before an item enters a sprint
Wwas by the numbers
- 83 all-time installs (skills.sh)
- Ranked #1,431 of 3,282 Productivity & Planning skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
wwas capabilities & compatibility
- Capabilities
- backlog management · acceptance criteria · sprint planning
- Use cases
- project management · planning · documentation
- Pricing
- Free
What wwas says it does
Why-What-Acceptance backlog format that connects every work item to strategic business objectives.
Before a WWAS item enters a sprint, it must pass the INVEST criteria
npx skills add https://github.com/borghei/claude-skills --skill wwasAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 83 |
|---|---|
| repo stars | ★ 451 |
| Last updated | July 21, 2026 |
| Repository | borghei/claude-skills ↗ |
What it does
Write backlog items in a Why-What-Acceptance format that connects each item to a business objective.
Who is it for?
Product teams building a backlog where strategic alignment of each item matters.
Skip if: Situation-driven requirements (use job stories) or pure technical tasks with no strategic context.
When should I use this skill?
Creating backlog items, refining sprint items, or decomposing a roadmap theme.
What you get
Backlog items with a strategic Why, a concise What, and observable acceptance criteria that pass INVEST.
- wwas backlog items
- acceptance criteria
- strategic why statements
By the numbers
- 3-part item format (Why/What/Acceptance)
- 4+ acceptance criteria per item
- 6 INVEST gates
Files
Why-What-Acceptance Backlog Expert
Overview
Create backlog items using the Why-What-Acceptance (WWAS) format. This format ensures every piece of work connects to strategic context, includes a concise description that serves as a "reminder of the discussion" rather than a detailed specification, and defines high-level acceptance criteria focused on observable outcomes.
When to Use
- Backlog creation -- When building a product backlog where strategic alignment is critical.
- Sprint planning -- When refining items for upcoming sprints and the team needs to understand why each item matters.
- Stakeholder communication -- When executives or cross-functional partners need to see how individual work items connect to business objectives.
- Roadmap decomposition -- When breaking down roadmap themes into actionable backlog items.
When NOT to Use
- When you need situation-driven requirements -- use
job-stories/instead. - When the work is a pure technical task with no strategic context (use a simple task description).
- When the team prefers traditional user story format and the strategic context is well-understood.
The WWAS Format
Every backlog item has three parts:
1. Why (Strategic Context)
1-2 sentences that connect this work item to the team's objectives and business strategy. The Why answers:
- What business objective does this support? (e.g., "Reduce churn by 10% in Q2")
- Why now? What makes this item timely or important relative to other work?
The Why is the most important part. It prevents the team from building features disconnected from strategy. If you cannot articulate the Why, the item should not be in the backlog.
Good Why examples:
- "Our Q2 objective is to reduce time-to-value for new users from 14 days to 3 days. Onboarding is the biggest lever -- 60% of churned users never completed setup."
- "Enterprise customers have cited lack of SSO as the top reason for not upgrading. This directly supports our revenue expansion target of $2M ARR growth in H1."
- "Support ticket volume for billing issues increased 40% last quarter. Resolving this frees up 2 support FTEs to focus on onboarding assistance, which supports our activation goal."
Bad Why examples (avoid):
- "Because the customer asked for it." (No strategic context)
- "It's a best practice." (No connection to team objectives)
- "We need this for the release." (Circular reasoning)
2. What (Description)
A short description of what needs to be built or changed. This section is a reminder of the discussion, not a detailed specification.
Guidelines:
- 1-2 paragraphs maximum.
- Describe the change at a level that reminds the team of what was discussed during refinement.
- Include a link to the design file if one exists.
- Do not write implementation details, technical specifications, or step-by-step instructions.
- The team should be able to read the What and say "Yes, I remember what we agreed to build."
Good What examples:
- "Add a guided setup wizard that walks new users through connecting their data source, inviting a teammate, and creating their first dashboard. The wizard should be skippable and resumable. [Design: Figma link]"
- "Replace the current billing FAQ page with an interactive troubleshooter that guides users through common billing issues (failed payments, plan changes, invoice requests) and resolves 80% of cases without a support ticket."
Bad What examples (avoid):
- A multi-page specification with wireframes, API contracts, and database schemas (too detailed -- that belongs in a design doc).
- "Build SSO." (Too vague -- the team cannot recall what was discussed).
3. Acceptance Criteria
High-level, observable outcomes that define when the item is done. These are not detailed test cases -- they are the minimum set of conditions that must be true for the item to be accepted.
Guidelines:
- 4 or more acceptance criteria per item.
- Each criterion describes an observable outcome, not an implementation step.
- Focus on what the user or system should do, not how it is built.
- Include the most important edge cases, but save exhaustive test cases for QA.
Good acceptance criteria examples:
1. New users who complete the setup wizard activate within 3 days (measured by creating their first dashboard). 2. The wizard is accessible on mobile and desktop browsers. 3. Users can skip the wizard at any step and resume later from where they left off. 4. Users who skip the wizard can access it again from the help menu.
Bad acceptance criteria examples (avoid):
- The API returns a 200 status code with a JSON payload containing... (implementation detail)
- The React component passes all unit tests (internal quality, not user outcome)
- It works on Chrome (too vague; specify what "works" means)
INVEST Quality Gates
Before a WWAS item enters a sprint, it must pass the INVEST criteria:
| Criterion | Question | Action If Failing |
|---|---|---|
| Independent | Can this item be delivered without waiting for another item? | Reorder the backlog or combine dependent items. |
| Negotiable | Is the What open to discussion on implementation approach? | Remove implementation prescriptions from the What. |
| Valuable | Does the Why connect to a real business objective? | Rewrite the Why or deprioritize the item. |
| Estimable | Can the team estimate effort with reasonable confidence? | Add more context to the What or conduct a spike. |
| Small | Can this be completed within one sprint? | Split the item (by outcome, by scope, or by user segment). |
| Testable | Can the acceptance criteria be verified? | Rewrite criteria to be observable and specific. |
Item Template
### [Title]
**Why:**
[1-2 sentences connecting to strategic objective and explaining why this matters now.]
**What:**
[1-2 paragraphs describing the change. Reminder of the discussion, not a specification.]
[Design: link or "TBD"]
**Acceptance Criteria:**
1. [ ] [Observable outcome]
2. [ ] [Observable outcome]
3. [ ] [Observable outcome]
4. [ ] [Observable outcome]Worked Example
Guided Onboarding Wizard
Why: Our Q2 North Star is reducing time-to-value from 14 days to 3 days. User research shows that 60% of churned users never completed the initial setup, and the top reason cited is "I did not know what to do next." A guided onboarding flow directly addresses this by walking users through the critical first steps.
What: Add a step-by-step setup wizard that appears on first login and guides new users through three milestones: connecting a data source, inviting a teammate, and creating their first dashboard. The wizard should be skippable at any point (some users prefer to explore on their own) and resumable if the user leaves before finishing. Each step includes a brief explanation of why it matters and a direct action button.
[Design: figma.com/file/abc123]
Acceptance Criteria:
1. [ ] The wizard appears automatically on first login for new users. 2. [ ] Users can skip the wizard at any step and return to it later from the help menu. 3. [ ] Each milestone (data source, teammate, dashboard) can be completed independently and in any order. 4. [ ] Users who complete all three milestones see a completion confirmation with suggested next steps. 5. [ ] The wizard does not appear for existing users who have already completed setup. 6. [ ] The wizard is functional on both desktop and mobile browsers.
Connecting Why to Business Objectives
The strength of WWAS is the explicit strategic connection. Use this mapping to write strong Why statements:
| Objective Level | Example Objective | Why Framing |
|---|---|---|
| Company OKR | Grow ARR to $10M | "This supports our $10M ARR target by..." |
| Team OKR | Reduce churn to <5% monthly | "Our team's Q2 churn target requires..." |
| Product theme | Self-serve onboarding | "As part of the self-serve onboarding theme..." |
| Customer feedback | Top 3 requested feature | "This is the #1 requested feature from enterprise customers, blocking $500K in pipeline..." |
| Operational | Reduce support load | "Support ticket volume for this issue is X/month, costing Y hours..." |
Integration with Other Skills
- Use
job-stories/when you need situation-driven stories focused on user context rather than strategic alignment. - Use
brainstorm-okrs/to define the objectives that WWAS items connect to. - Use
summarize-meeting/to capture refinement session discussions that inform the What. - Feed WWAS items into
../jira-expert/for ticket creation with structured fields.
References
- See
references/backlog-management-guide.mdfor format comparison, INVEST deep dive, and refinement best practices. - See
assets/wwas_template.mdfor ready-to-use templates.
Troubleshooting
| Problem | Likely Cause | Resolution |
|---|---|---|
| "Why" statements are generic ("Because the customer asked for it") | PM did not connect the request to a business objective; strategic context unclear | Require every Why to reference a specific OKR, metric, or business case; use the objective-level mapping table in this skill |
| "What" descriptions are either too vague or too detailed | Team unclear on the "reminder of discussion" principle; no refinement session occurred | Run a refinement session before writing the What; enforce the 1-2 paragraph limit; link to design docs for details |
| Acceptance criteria describe implementation steps | Engineering team wrote criteria without user-facing framing | Apply the "would the user care?" filter; rewrite every criterion as an observable outcome; remove API/database references |
| Items consistently fail the INVEST-S (Small) gate | Scope creep during refinement; team reluctant to split items | Practice vertical slicing: split by user segment, by scenario, or by outcome; target items completable in 3-5 days |
| Backlog items lose strategic connection over time | Why statements written once and never revisited; OKRs shift without backlog update | Review backlog alignment quarterly; update or retire items whose Why no longer connects to current objectives |
| Team finds WWAS format overhead compared to simple user stories | Format adds friction without perceived value; team already has strong strategic context | Use WWAS for high-priority items and features; allow simpler formats for bugs and technical tasks; demonstrate value by showing how Why prevents wasted work |
| Acceptance criteria are too few or too shallow | Team rushes through refinement; criteria treated as a checkbox exercise | Set minimum of 4 acceptance criteria per item; include at least 1 edge case and 1 error state criterion |
Success Criteria
- 100% of feature backlog items include a Why statement referencing a specific business objective or OKR
- What descriptions are 1-2 paragraphs and link to design documentation when applicable
- Every item has at least 4 acceptance criteria focused on observable user outcomes
- All sprint-ready items pass the full INVEST quality gate before entering a sprint
- Stakeholders can read any backlog item's Why and confirm strategic alignment without additional context
- Items written in WWAS format have a 30%+ lower rejection rate at sprint review compared to items without strategic context
- Backlog alignment review occurs at least quarterly, with outdated items retired or updated
Scope & Limitations
In Scope: Writing backlog items in Why-What-Acceptance format, applying INVEST quality gates, connecting work items to strategic objectives, facilitating refinement sessions to produce WWAS items, converting existing backlog items to WWAS format, integrating with Jira for ticket creation.
Out of Scope: Situation-driven requirements (hand off to job-stories/), product ideation and opportunity discovery (hand off to discovery/brainstorm-ideas/), OKR definition (hand off to execution/brainstorm-okrs/), detailed technical specifications, sprint planning and capacity management (hand off to ../scrum-master/).
Limitations: WWAS format adds most value when the organization has clearly defined objectives (OKRs, North Star metrics). Without strategic context, the Why becomes a forced exercise with limited benefit. The format is designed for product/feature work -- purely technical debt or infrastructure items may not fit naturally. Teams transitioning from user stories may need 2-3 sprints to build fluency with the format.
Integration Points
| Integration | Direction | What Flows |
|---|---|---|
job-stories/ | Complementary | Job stories add situational context (When); WWAS adds strategic context (Why). Use both for complete requirements |
summarize-meeting/ | Meetings -> WWAS | Refinement session discussions produce the What; decisions produce acceptance criteria |
../jira-expert/ | WWAS -> Jira | WWAS items become Jira tickets with structured description fields |
execution/brainstorm-okrs/ | OKRs -> WWAS | Team OKRs provide the strategic objectives that Why statements reference |
execution/prioritization-frameworks/ | WWAS -> Prioritization | WWAS items scored via RICE or other frameworks for backlog ordering |
discovery/brainstorm-ideas/ | Ideas -> WWAS | Validated ideas decompose into WWAS backlog items with strategic traceability |
WWAS Templates
Single WWAS Backlog Item
[Title -- Short, Descriptive Name]
Why: [1-2 sentences connecting to a strategic objective, OKR, or business goal. Explain why this matters and why now.]
What: [1-2 paragraphs describing the change. This is a reminder of the discussion, not a detailed specification. The team should read this and recall what was agreed.]
[Design: link to Figma / Sketch / wireframe, or "TBD"]
Acceptance Criteria:
1. [ ] [Observable outcome that defines done] 2. [ ] [Observable outcome under a specific condition] 3. [ ] [Edge case or error state handling] 4. [ ] [Performance, accessibility, or cross-platform criterion]
INVEST Check:
| Criterion | Pass? | Notes |
|---|---|---|
| Independent | [ ] | No blocking dependencies |
| Negotiable | [ ] | Implementation open to discussion |
| Valuable | [ ] | Clear user or business value |
| Estimable | [ ] | Team can size this confidently |
| Small | [ ] | Fits within one sprint |
| Testable | [ ] | Acceptance criteria are verifiable |
Estimate: [Story points or T-shirt size] Priority: [P0 / P1 / P2 / P3] Sprint: [Target sprint or "Backlog"]
---
Batch WWAS Template
Use this table to draft multiple items quickly, then expand the highest-priority items into full cards.
| # | Title | Why (objective connection) | What (brief description) | AC Count | Estimate | Priority |
|---|---|---|---|---|---|---|
| 1 | ||||||
| 2 | ||||||
| 3 | ||||||
| 4 | ||||||
| 5 | ||||||
| 6 | ||||||
| 7 | ||||||
| 8 |
Batch Review Checklist
- [ ] Every item has a Why that references a specific objective or metric
- [ ] No item's What reads like a specification (1-2 paragraphs max)
- [ ] Each item has 4+ acceptance criteria
- [ ] All items pass INVEST (especially Independent and Small)
- [ ] Items are ordered by priority
- [ ] Design links are included where applicable
---
Refinement Session Template
Use this template to structure a backlog refinement session around WWAS items.
Refinement Session -- [Date]
Attendees: [Names and roles] Duration: [Time] minutes Items to Refine: [Number]
Pre-Refinement Preparation
- [ ] Items shared with the team 24 hours in advance
- [ ] Design artifacts linked and accessible
- [ ] Previous refinement action items reviewed
Agenda
| Time | Activity |
|---|---|
| 5 min | Review action items from last refinement |
| 5 min per item | Walk through each item: Why, What, Acceptance Criteria |
| 5 min | Estimate refined items |
| 5 min | Identify items needing spikes or follow-up |
Item-by-Item Notes
Item: [Title]
- Why discussion: [Notes on strategic alignment -- did the team agree?]
- What discussion: [Notes on scope -- any changes to the description?]
- AC discussion: [Notes on acceptance criteria -- additions, removals, changes?]
- Estimate: [Story points or T-shirt size]
- Status: Ready / Needs spike / Needs design / Needs follow-up
- Follow-up: [Any actions needed before this is sprint-ready]
(Repeat for each item)
Session Outcomes
- Items refined: [Count]
- Items ready for sprint: [Count]
- Items needing follow-up: [Count]
- Spikes identified: [List]
- Next refinement: [Date]
Backlog Management Guide
WWAS Format Explained
Why-What-Acceptance (WWAS) is a backlog item format designed to ensure strategic alignment without over-specifying implementation. It was developed as a response to two common failure modes:
1. Backlog items with no strategic context -- Teams build features without understanding why they matter, leading to disconnected product decisions and difficulty prioritizing. 2. Backlog items that are over-specified -- Detailed specifications masquerading as backlog items remove the team's ability to negotiate implementation and slow down refinement.
WWAS solves both by requiring a strategic Why, keeping the What brief, and defining acceptance through observable outcomes.
The Three Parts
Why (1-2 sentences): Connects the item to a business objective, OKR, or strategic theme. Answers "Why does this matter?" and "Why now?" If you cannot write a compelling Why, the item should not be prioritized.
What (1-2 paragraphs): A reminder of what was discussed during refinement. Not a specification. The team should read this and recall the conversation. Includes a design link if applicable.
Acceptance Criteria (4+ items): Observable outcomes that define done. Not implementation steps. Not test scripts. Just the conditions that must be true for the team to consider the item complete.
Comparison with User Stories and Job Stories
| Aspect | User Story | Job Story | WWAS |
|---|---|---|---|
| Format | As a [role], I want [action], so that [benefit] | When [situation], I want [motivation], so I can [outcome] | Why / What / Acceptance |
| Strength | Simple, role-centric | Situation-centric, design-friendly | Strategy-centric, business-aligned |
| Strategic context | Minimal (the "so that" is often weak) | Minimal (focuses on user outcome) | Explicit (the Why section) |
| Specification level | Varies widely | Moderate | Intentionally brief |
| Best for | Teams familiar with agile basics | Design-driven product teams | Strategy-conscious product teams |
| Risk | Becomes formulaic, loses meaning | Requires deep user research | Why can become boilerplate if not genuine |
When to Use Each
- User Stories -- When the team is agile-fluent and roles are well-defined. Good for CRUD features and internal tools.
- Job Stories -- When you need to deeply understand user situations and design for context. Good for consumer products and UX-heavy work.
- WWAS -- When strategic alignment is the primary concern. Good for enterprise products, teams with business stakeholders, and roadmap-driven development.
You can mix formats within the same backlog. Use the format that best serves each item.
INVEST Criteria Deep Dive
Independent
Definition: The item can be developed, tested, and delivered without requiring another item to be completed first.
Why it matters: Dependent items create scheduling constraints, block parallel work, and increase the risk of partial delivery.
How to check:
- Can the team start this item on day one of the sprint without waiting?
- Can this item be released to users on its own?
- If another item is delayed, does this item still make sense?
How to fix dependencies:
- Combine small dependent items into one larger item.
- Redefine the item boundary to include the dependency.
- Extract the shared dependency as its own item and schedule it first.
Negotiable
Definition: The item describes what and why, not how. The implementation approach is open for the team to decide.
Why it matters: Prescriptive items prevent the team from applying their expertise, reduce ownership, and miss opportunities for simpler solutions.
How to check:
- Does the What section mention specific technologies, UI patterns, or architecture?
- Could the team solve this in at least two different ways?
- Is the design link a constraint or a starting point for discussion?
How to fix:
- Remove implementation details from the What.
- Replace "Build a dropdown menu" with "Allow the user to select from available options."
- Move technical specifications to a linked design document.
Valuable
Definition: The item delivers value that a user or business stakeholder cares about.
Why it matters: Items without clear value consume capacity without moving the needle. They also demoralize teams who cannot see the impact of their work.
How to check:
- Does the Why connect to a real, measurable business objective?
- Would a user notice or care if this item were shipped?
- Can you explain the value to a non-technical stakeholder in one sentence?
How to fix:
- Rewrite the Why with a specific objective and metric.
- If the item is purely technical (refactoring, upgrades), frame the Why in terms of what it enables or unblocks.
- If no value can be articulated, reconsider whether the item belongs in the backlog.
Estimable
Definition: The team can estimate the effort required with reasonable confidence.
Why it matters: Unestimable items indicate insufficient understanding, which leads to surprises during implementation.
How to check:
- Can the team provide a story point estimate or T-shirt size?
- Is the team's confidence level above 60%?
- Are there known unknowns that would change the estimate significantly?
How to fix:
- Add more context to the What section.
- Conduct a time-boxed spike to reduce uncertainty.
- Split the item so the uncertain part becomes its own research item.
Small
Definition: The item can be completed within one sprint.
Why it matters: Large items are harder to estimate, harder to test, and create integration risk. They also delay feedback.
How to fix (splitting strategies):
- By outcome: Split acceptance criteria into separate items.
- By scope: Deliver the happy path first, edge cases second.
- By user segment: Build for one segment first, extend to others later.
- By operation: Split CRUD operations into separate items.
Testable
Definition: The acceptance criteria can be verified through observation or measurement.
Why it matters: Untestable items cannot be definitively completed, leading to ambiguity about done-ness and scope creep.
How to check:
- Can QA write test cases from the acceptance criteria alone?
- Is each criterion binary (pass/fail), not subjective?
- Are edge cases covered?
How to fix:
- Replace vague criteria ("it works") with specific outcomes ("the page loads in under 2 seconds").
- Add error state criteria ("if the payment fails, the user sees an error message with a retry option").
- Remove subjective criteria ("the UI is intuitive") or replace with measurable proxies ("new users complete the flow without help text in under 3 minutes").
Backlog Refinement Best Practices
Before Refinement
1. Product owner prepares draft items with Why and What filled in. Acceptance criteria can be rough. 2. Share items 24 hours in advance so the team can review and come with questions. 3. Limit the agenda to 5-8 items per session. Quality over quantity.
During Refinement
1. Start with the Why. Before discussing What or How, ensure the team understands and agrees with the strategic context. 2. Discuss, do not dictate. The product owner presents the item; the team asks questions and proposes approaches. 3. Write acceptance criteria together. The team's input ensures criteria are realistic and testable. 4. Apply INVEST. Check each criterion before moving to the next item. 5. Estimate after discussion. Estimation is more accurate when the team has discussed the item. 6. Timebox each item. If an item takes more than 10 minutes, park it and schedule a deeper discussion.
After Refinement
1. Update items with the discussed changes. 2. Link design artifacts if new designs were referenced. 3. Flag items that need spikes and schedule the spike for the current sprint. 4. Communicate priority changes to stakeholders if the order shifted.
Definition of Ready Checklist
An item is ready for sprint planning when:
- [ ] Why is written and connects to a current team objective
- [ ] What is clear enough that the team recalls the discussion
- [ ] Acceptance criteria include 4+ observable outcomes
- [ ] Design is linked (if applicable) and reviewed by the team
- [ ] INVEST criteria are satisfied
- [ ] Estimate has been provided by the team
- [ ] Dependencies are resolved or explicitly managed
- [ ] Questions from refinement are answered
When to Use WWAS vs Other Formats
| Signal | Recommended Format |
|---|---|
| Stakeholders ask "Why are we building this?" | WWAS -- the Why section directly answers this |
| Team builds features that do not move metrics | WWAS -- forces strategic connection |
| Designers need more context about user situations | Job Stories -- situation component drives design |
| Team is new to structured requirements | User Stories -- simplest format to learn |
| Backlog items are over-specified | WWAS -- the What is intentionally brief |
| Backlog items are under-specified | WWAS or Job Stories -- both require meaningful context |
| Mix of strategic and tactical items | WWAS for strategic, simple tasks for tactical |
#!/usr/bin/env python3
"""Backlog Alignment Checker - Check WWAS backlog items for strategic alignment.
Reads WWAS items and validates each Why statement against defined OKRs,
identifying orphaned items and strategic gaps.
Usage:
python backlog_alignment_checker.py --backlog backlog.json
python backlog_alignment_checker.py --backlog backlog.json --json
python backlog_alignment_checker.py --example
"""
import argparse
import json
import re
import sys
def load_data(path: str) -> dict:
with open(path, "r") as f:
return json.load(f)
def check_alignment(data: dict) -> dict:
okrs = data.get("okrs", [])
items = data.get("items", [])
okr_keywords = {}
for okr in okrs:
okr_id = okr.get("id", "")
okr_name = okr.get("name", "")
keywords = okr.get("keywords", [])
# Also extract words from the OKR name
name_words = [w.lower() for w in re.findall(r'\w+', okr_name) if len(w) > 3]
okr_keywords[okr_id] = {
"name": okr_name,
"keywords": [k.lower() for k in keywords] + name_words,
}
results = []
aligned = 0
unaligned = 0
okr_coverage = {okr_id: 0 for okr_id in okr_keywords}
for item in items:
title = item.get("title", "Untitled")
why = item.get("why", "").lower()
what = item.get("what", "")
acceptance_criteria = item.get("acceptance_criteria", [])
explicit_okr = item.get("okr_ref", "")
# Check explicit OKR reference
matched_okrs = []
if explicit_okr and explicit_okr in okr_keywords:
matched_okrs.append(explicit_okr)
# Check keyword matching
for okr_id, okr_info in okr_keywords.items():
if okr_id in matched_okrs:
continue
for kw in okr_info["keywords"]:
if kw in why:
matched_okrs.append(okr_id)
break
is_aligned = len(matched_okrs) > 0
# Quality checks on Why
why_quality = "Good"
why_issues = []
if not why or len(why) < 20:
why_quality = "Missing"
why_issues.append("Why statement is missing or too short")
elif any(phrase in why for phrase in ["customer asked", "best practice", "need this", "just because"]):
why_quality = "Weak"
why_issues.append("Why uses generic rationale -- connect to a specific metric or OKR")
# WWAS completeness
has_why = len(why) >= 20
has_what = len(what) >= 30
has_ac = len(acceptance_criteria) >= 4
completeness = sum([has_why, has_what, has_ac])
if is_aligned:
aligned += 1
for okr_id in matched_okrs:
okr_coverage[okr_id] = okr_coverage.get(okr_id, 0) + 1
else:
unaligned += 1
results.append({
"title": title,
"is_aligned": is_aligned,
"matched_okrs": [okr_keywords[oid]["name"] for oid in matched_okrs if oid in okr_keywords],
"why_quality": why_quality,
"why_issues": why_issues,
"completeness": {
"has_why": has_why,
"has_what": has_what,
"has_acceptance_criteria": has_ac,
"score": f"{completeness}/3",
},
})
# OKR coverage analysis
uncovered_okrs = [okr_keywords[oid]["name"] for oid, count in okr_coverage.items() if count == 0]
heavily_loaded = [(okr_keywords[oid]["name"], count) for oid, count in okr_coverage.items() if count > 5]
alignment_rate = round(aligned / len(items) * 100, 1) if items else 0
recs = []
if unaligned > 0:
recs.append(f"{unaligned} backlog item(s) not aligned to any OKR. Review and either connect to objectives or deprioritize.")
if uncovered_okrs:
recs.append(f"OKRs with no backlog items: {', '.join(uncovered_okrs[:3])}. Create WWAS items to support these objectives.")
if heavily_loaded:
for name, count in heavily_loaded:
recs.append(f"OKR '{name}' has {count} items. Check if scope is too broad or items need re-scoping.")
weak_whys = [r for r in results if r["why_quality"] == "Weak"]
if weak_whys:
recs.append(f"{len(weak_whys)} item(s) with weak Why statements. Strengthen with specific metrics, OKR references, or customer evidence.")
return {
"total_items": len(items),
"aligned": aligned,
"unaligned": unaligned,
"alignment_rate_pct": alignment_rate,
"okr_coverage": {okr_keywords[oid]["name"]: count for oid, count in okr_coverage.items()},
"uncovered_okrs": uncovered_okrs,
"items": results,
"recommendations": recs,
}
def print_report(result: dict) -> None:
print(f"\nBacklog Alignment Check")
print(f"Items: {result['total_items']} | Alignment: {result['alignment_rate_pct']:.0f}%")
print("=" * 65)
print(f"Aligned: {result['aligned']} | Unaligned: {result['unaligned']}")
print(f"\nOKR Coverage:")
for okr, count in result["okr_coverage"].items():
bar = "#" * min(count, 20)
indicator = " (NO ITEMS)" if count == 0 else ""
print(f" {okr[:35]:<35} {count:>3} items {bar}{indicator}")
print(f"\nItem Details:")
for item in result["items"]:
status = "OK" if item["is_aligned"] else "!!"
okrs = ", ".join(item["matched_okrs"]) if item["matched_okrs"] else "NONE"
print(f" [{status}] {item['title'][:35]:<35} Why: {item['why_quality']:<8} OKRs: {okrs}")
for issue in item["why_issues"]:
print(f" ! {issue}")
if result["recommendations"]:
print(f"\nRecommendations:")
for i, r in enumerate(result["recommendations"], 1):
print(f" {i}. {r}")
print()
def print_example() -> None:
example = {
"okrs": [
{"id": "OKR-1", "name": "Reduce churn to <5% monthly", "keywords": ["churn", "retention", "activation"]},
{"id": "OKR-2", "name": "Grow ARR to $10M", "keywords": ["revenue", "ARR", "enterprise", "upsell"]},
{"id": "OKR-3", "name": "Improve developer experience", "keywords": ["developer", "DX", "API", "documentation"]},
],
"items": [
{
"title": "Guided Onboarding Wizard",
"why": "Our Q2 objective is to reduce churn. 60% of churned users never completed setup.",
"what": "Add a step-by-step setup wizard for new users.",
"acceptance_criteria": ["Wizard appears on first login", "Can be skipped", "Progress saved", "Completion confirmation shown"],
"okr_ref": "OKR-1",
},
{
"title": "Admin Dashboard Polish",
"why": "Because the customer asked for it.",
"what": "Clean up the admin dashboard UI.",
"acceptance_criteria": ["Looks better"],
},
{
"title": "API Rate Limit Docs",
"why": "Developer support tickets about rate limits increased 40% last quarter, costing 10 hours/week.",
"what": "Create comprehensive rate limit documentation with examples and troubleshooting guide.",
"acceptance_criteria": ["Docs cover all endpoints", "Includes code examples", "FAQ section", "Linked from API portal"],
},
],
}
print(json.dumps(example, indent=2))
def main():
parser = argparse.ArgumentParser(description="Check WWAS backlog alignment with OKRs.")
parser.add_argument("--backlog", type=str, help="Path to backlog JSON file")
parser.add_argument("--json", action="store_true", help="Output as JSON")
parser.add_argument("--example", action="store_true", help="Print example and exit")
args = parser.parse_args()
if args.example:
print_example()
return
if not args.backlog:
parser.error("--backlog is required")
data = load_data(args.backlog)
result = check_alignment(data)
if args.json:
print(json.dumps(result, indent=2))
else:
print_report(result)
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""INVEST Gate Checker - Validate WWAS items against INVEST quality gates.
Reads WWAS backlog items and checks each against the 6 INVEST criteria
with actionable fix suggestions for failing items.
Usage:
python invest_gate_checker.py --items items.json
python invest_gate_checker.py --items items.json --json
python invest_gate_checker.py --example
"""
import argparse
import json
import re
import sys
def load_data(path: str) -> dict:
with open(path, "r") as f:
return json.load(f)
def check_invest(item: dict) -> dict:
title = item.get("title", "Untitled")
why = item.get("why", "")
what = item.get("what", "")
acceptance_criteria = item.get("acceptance_criteria", [])
dependencies = item.get("dependencies", [])
story_points = item.get("story_points")
gates = {}
# Independent
blocked = len(dependencies) > 0
gates["independent"] = {
"passed": not blocked,
"detail": f"Blocked by: {', '.join(dependencies)}" if blocked else "No blocking dependencies",
"action": "Reorder backlog or combine dependent items" if blocked else None,
}
# Negotiable
prescriptive_patterns = [r"\bmust use\b", r"\bimplement with\b", r"\buse \w+ framework\b", r"\brequires?\s+\w+\s+library\b"]
is_prescriptive = any(re.search(p, what, re.IGNORECASE) for p in prescriptive_patterns)
gates["negotiable"] = {
"passed": not is_prescriptive,
"detail": "What prescribes implementation approach" if is_prescriptive else "Implementation approach is open",
"action": "Remove technology/implementation specifics from What -- describe the outcome, not the solution" if is_prescriptive else None,
}
# Valuable
has_value = len(why) >= 30 and not any(re.search(p, why, re.IGNORECASE) for p in [r"customer asked", r"best practice", r"we need this"])
gates["valuable"] = {
"passed": has_value,
"detail": "Why connects to business objective" if has_value else "Why is missing or lacks strategic context",
"action": "Rewrite Why to reference a specific OKR, metric, or customer evidence" if not has_value else None,
}
# Estimable
enough_context = len(what) >= 50 and len(acceptance_criteria) >= 3
gates["estimable"] = {
"passed": enough_context,
"detail": f"What: {len(what)} chars, {len(acceptance_criteria)} AC" if enough_context else "Insufficient detail for estimation",
"action": "Add more context to What and provide at least 4 acceptance criteria" if not enough_context else None,
}
# Small
if story_points is not None:
is_small = story_points <= 8
size_detail = f"Story points: {story_points}"
else:
# Heuristic: many AC = potentially large
is_small = len(acceptance_criteria) <= 8 and len(what) < 500
size_detail = f"{len(acceptance_criteria)} AC, {len(what)} chars description"
gates["small"] = {
"passed": is_small,
"detail": size_detail if is_small else f"Likely too large: {size_detail}",
"action": "Split by user segment, scenario, or outcome to fit one sprint" if not is_small else None,
}
# Testable
observable_patterns = [r"\bshows\b", r"\bdisplays\b", r"\benables\b", r"\bprevents\b", r"\bnotifies\b", r"\bwithin\b", r"\bwhen\b", r"\bif\b", r"\bless than\b", r"\bmore than\b"]
testable_count = sum(1 for ac in acceptance_criteria if any(re.search(p, ac, re.IGNORECASE) for p in observable_patterns))
is_testable = testable_count >= 2 or len(acceptance_criteria) >= 4
gates["testable"] = {
"passed": is_testable,
"detail": f"{testable_count}/{len(acceptance_criteria)} criteria clearly testable" if acceptance_criteria else "No acceptance criteria",
"action": "Rewrite criteria as observable outcomes: '[Thing] [does] [expected behavior] [under condition]'" if not is_testable else None,
}
passed = sum(1 for g in gates.values() if g["passed"])
total = len(gates)
if passed == 6:
verdict = "PASS - Sprint Ready"
elif passed >= 4:
verdict = "CONDITIONAL - Fix before sprint"
else:
verdict = "FAIL - Needs refinement"
actions = [{"gate": k, "action": v["action"]} for k, v in gates.items() if v.get("action")]
return {
"title": title,
"passed": passed,
"total": total,
"verdict": verdict,
"gates": gates,
"required_actions": actions,
}
def analyze_items(data: dict) -> dict:
items = data.get("items", [])
results = [check_invest(item) for item in items]
pass_count = sum(1 for r in results if "PASS" in r["verdict"])
conditional = sum(1 for r in results if "CONDITIONAL" in r["verdict"])
fail_count = sum(1 for r in results if "FAIL" in r["verdict"])
# Most common failing gates
gate_fails = {}
for r in results:
for gate, info in r["gates"].items():
if not info["passed"]:
gate_fails[gate] = gate_fails.get(gate, 0) + 1
return {
"total_items": len(results),
"passed": pass_count,
"conditional": conditional,
"failed": fail_count,
"common_failures": sorted(gate_fails.items(), key=lambda x: x[1], reverse=True),
"items": results,
}
def print_report(result: dict) -> None:
print(f"\nINVEST Gate Check (WWAS)")
print(f"Items: {result['total_items']}")
print("=" * 60)
print(f"Pass: {result['passed']} | Conditional: {result['conditional']} | Fail: {result['failed']}")
if result["common_failures"]:
print(f"\nMost Common Failures:")
for gate, count in result["common_failures"]:
print(f" {gate.upper()}: {count} item(s)")
for item in result["items"]:
print(f"\n [{item['verdict']}] {item['title']} ({item['passed']}/{item['total']})")
for gate, info in item["gates"].items():
status = "PASS" if info["passed"] else "FAIL"
print(f" [{status}] {gate.upper()}: {info['detail']}")
if item["required_actions"]:
for action in item["required_actions"]:
print(f" -> {action['gate'].upper()}: {action['action']}")
print()
def print_example() -> None:
example = {
"items": [
{
"title": "Guided Onboarding Wizard",
"why": "Our Q2 North Star is reducing time-to-value from 14 days to 3 days. 60% of churned users never completed setup.",
"what": "Add a step-by-step setup wizard for new users covering data source connection, teammate invite, and first dashboard creation.",
"acceptance_criteria": [
"Wizard appears on first login",
"Users can skip and resume later",
"Milestones completable in any order",
"Completion shows next steps",
"If no data source available, shows sample data option",
],
"dependencies": [],
"story_points": 5,
},
{
"title": "Rebuild Everything",
"why": "We need this.",
"what": "Rebuild. Must use React 19 and implement with GraphQL.",
"acceptance_criteria": ["It works"],
"dependencies": ["API v3", "DB migration"],
"story_points": 40,
},
],
}
print(json.dumps(example, indent=2))
def main():
parser = argparse.ArgumentParser(description="Check WWAS items against INVEST gates.")
parser.add_argument("--items", type=str, help="Path to items JSON file")
parser.add_argument("--json", action="store_true", help="Output as JSON")
parser.add_argument("--example", action="store_true", help="Print example and exit")
args = parser.parse_args()
if args.example:
print_example()
return
if not args.items:
parser.error("--items is required")
data = load_data(args.items)
result = analyze_items(data)
if args.json:
print(json.dumps(result, indent=2))
else:
print_report(result)
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""WWAS Quality Scorer - Score WWAS backlog items for completeness and quality.
Reads WWAS items and evaluates the quality of Why, What, and Acceptance
Criteria sections against best practices.
Usage:
python wwas_quality_scorer.py --items items.json
python wwas_quality_scorer.py --items items.json --json
python wwas_quality_scorer.py --example
"""
import argparse
import json
import re
import sys
WEAK_WHY_PATTERNS = [
r"customer asked",
r"best practice",
r"need this for",
r"we need",
r"requirement",
r"it\'s important",
r"because we should",
]
IMPL_DETAIL_PATTERNS = [
r"\bAPI\b", r"\b200\b", r"\bJSON\b", r"\brender\b",
r"\bunit test\b", r"\bdatabase\b", r"\bSQL\b", r"\bCSS\b",
r"\bcomponent\b", r"\bReact\b", r"\bendpoint\b",
]
def load_data(path: str) -> dict:
with open(path, "r") as f:
return json.load(f)
def score_item(item: dict) -> dict:
title = item.get("title", "Untitled")
why = item.get("why", "").strip()
what = item.get("what", "").strip()
acceptance_criteria = item.get("acceptance_criteria", [])
design_link = item.get("design_link", "")
score = 0
max_score = 100
checks = {}
# WHY quality (35 points)
why_score = 0
why_issues = []
if not why:
why_issues.append("Why is missing entirely")
elif len(why) < 30:
why_score = 5
why_issues.append("Why is too brief -- add strategic context")
else:
why_score = 10
# Check for metric reference
if re.search(r'\d+%|\$\d|#\d|\d+[xX]', why):
why_score += 10 # Has quantitative reference
else:
why_issues.append("Why lacks quantitative metrics (e.g., '40% increase', '$500K pipeline')")
why_score += 5
# Check for weak patterns
if any(re.search(p, why, re.IGNORECASE) for p in WEAK_WHY_PATTERNS):
why_issues.append("Why uses generic rationale -- connect to a specific business objective")
why_score = max(5, why_score - 5)
else:
why_score += 5
# Check for OKR/objective reference
if re.search(r'Q[1-4]|OKR|objective|target|goal|north star', why, re.IGNORECASE):
why_score += 10
else:
why_issues.append("Why does not reference a specific OKR or business objective")
why_score += 5
checks["why"] = {"score": min(35, why_score), "max": 35, "issues": why_issues}
score += min(35, why_score)
# WHAT quality (30 points)
what_score = 0
what_issues = []
if not what:
what_issues.append("What is missing entirely")
elif len(what) < 50:
what_score = 5
what_issues.append("What is too brief -- should be a reminder of the discussion (1-2 paragraphs)")
elif len(what) > 1000:
what_score = 15
what_issues.append("What is too detailed -- this should be a reminder, not a specification. Move details to a design doc.")
else:
what_score = 20
if design_link:
what_score += 10
elif what and len(what) > 50:
what_issues.append("No design link provided (add if design exists)")
what_score += 5
checks["what"] = {"score": min(30, what_score), "max": 30, "issues": what_issues}
score += min(30, what_score)
# ACCEPTANCE CRITERIA quality (35 points)
ac_score = 0
ac_issues = []
ac_count = len(acceptance_criteria)
if ac_count == 0:
ac_issues.append("No acceptance criteria defined")
elif ac_count < 4:
ac_score = 10
ac_issues.append(f"Only {ac_count} criteria (minimum: 4)")
else:
ac_score = 15
# Check for implementation details in AC
impl_count = 0
for ac in acceptance_criteria:
if any(re.search(p, ac, re.IGNORECASE) for p in IMPL_DETAIL_PATTERNS):
impl_count += 1
if impl_count > 0:
ac_issues.append(f"{impl_count} criteria contain implementation details -- rewrite as observable user outcomes")
ac_score = max(5, ac_score - 5)
elif ac_count > 0:
ac_score += 10
# Check for edge cases
edge_words = [r"error", r"empty", r"no data", r"invalid", r"fails", r"timeout", r"edge"]
has_edge_case = any(any(re.search(w, ac, re.IGNORECASE) for w in edge_words) for ac in acceptance_criteria)
if has_edge_case:
ac_score += 10
elif ac_count >= 4:
ac_issues.append("No edge case or error state criteria -- add at least 1")
ac_score += 5
checks["acceptance_criteria"] = {"score": min(35, ac_score), "max": 35, "count": ac_count, "issues": ac_issues}
score += min(35, ac_score)
score = max(0, min(100, score))
if score >= 80:
rating = "Sprint Ready"
elif score >= 55:
rating = "Needs Refinement"
else:
rating = "Not Ready"
all_issues = checks["why"]["issues"] + checks["what"]["issues"] + checks["acceptance_criteria"]["issues"]
return {
"title": title,
"score": score,
"rating": rating,
"why_score": checks["why"]["score"],
"what_score": checks["what"]["score"],
"ac_score": checks["acceptance_criteria"]["score"],
"ac_count": ac_count,
"issues": all_issues,
"checks": checks,
}
def analyze_items(data: dict) -> dict:
items = data.get("items", [])
results = [score_item(item) for item in items]
scores = [r["score"] for r in results]
avg = round(sum(scores) / len(scores), 1) if scores else 0
ready = sum(1 for r in results if r["rating"] == "Sprint Ready")
needs_work = sum(1 for r in results if r["rating"] == "Needs Refinement")
not_ready = sum(1 for r in results if r["rating"] == "Not Ready")
return {
"total_items": len(results),
"average_score": avg,
"sprint_ready": ready,
"needs_refinement": needs_work,
"not_ready": not_ready,
"items": results,
}
def print_report(result: dict) -> None:
print(f"\nWWAS Quality Report")
print(f"Items: {result['total_items']} | Avg Score: {result['average_score']:.0f}/100")
print("=" * 65)
print(f"Sprint Ready: {result['sprint_ready']} | Needs Refinement: {result['needs_refinement']} | Not Ready: {result['not_ready']}")
print(f"\n {'Title':<30} {'Score':>6} {'Why':>5} {'What':>5} {'AC':>5} {'Rating'}")
print(f" {'-'*30} {'-'*6} {'-'*5} {'-'*5} {'-'*5} {'-'*16}")
for item in sorted(result["items"], key=lambda x: x["score"]):
title = item["title"][:28] + ".." if len(item["title"]) > 30 else item["title"]
print(f" {title:<30} {item['score']:>5}% {item['why_score']:>4} {item['what_score']:>4} {item['ac_score']:>4} {item['rating']}")
for issue in item["issues"][:2]:
print(f" ! {issue}")
print()
def print_example() -> None:
example = {
"items": [
{
"title": "Guided Onboarding Wizard",
"why": "Our Q2 North Star is reducing time-to-value from 14 days to 3 days. 60% of churned users never completed setup.",
"what": "Add a step-by-step setup wizard that guides new users through connecting a data source, inviting a teammate, and creating their first dashboard. Skippable and resumable.",
"design_link": "https://figma.com/file/abc123",
"acceptance_criteria": [
"Wizard appears automatically on first login for new users",
"Users can skip at any step and return from help menu",
"Each milestone completable independently in any order",
"Completion confirmation with suggested next steps",
"Does not appear for existing users who completed setup",
"Functional on desktop and mobile browsers",
],
},
{
"title": "Fix UI Bug",
"why": "Customer asked for it.",
"what": "Fix the button.",
"acceptance_criteria": ["API returns 200"],
},
],
}
print(json.dumps(example, indent=2))
def main():
parser = argparse.ArgumentParser(description="Score WWAS backlog item quality.")
parser.add_argument("--items", type=str, help="Path to items JSON file")
parser.add_argument("--json", action="store_true", help="Output as JSON")
parser.add_argument("--example", action="store_true", help="Print example and exit")
args = parser.parse_args()
if args.example:
print_example()
return
if not args.items:
parser.error("--items is required")
data = load_data(args.items)
result = analyze_items(data)
if args.json:
print(json.dumps(result, indent=2))
else:
print_report(result)
if __name__ == "__main__":
main()
Related skills
FAQ
What are the three parts of a WWAS item?
Why (strategic context connecting to objectives), What (a concise reminder of the discussion, not a spec), and Acceptance Criteria (observable outcomes).
What quality gate does it use?
INVEST: Independent, Negotiable, Valuable, Estimable, Small, with actions to fix each failing criterion before an item enters a sprint.