risk-matrix
The risk-based testing (RBT) umbrella: risk matrix and risk register authoring, likelihood x impact scoring, risk storming, calibration, and risk-to-test coverage mapping. Produces the per-feature / per-release matrix artifact (structured intake: feature, category, impact 1-5 by likelihood 1-5, score; heatmap; mitigations with owners and due dates), supporting lightweight and heavyweight (FMEA / Cost of Exposure) methods per RBT canon, plus a risk coverage mapping workflow that proves which tests, cases, or monitors back each registered risk. references/ carries the product-risk and project-risk register variants, the risk-storming facilitation guide, matrix calibration against observed defect data, and a register review checklist. Use for any risk-based-testing artifact: building a matrix or register, running a risk-storming session, calibrating ratings against defects, or mapping risks onto test coverage.
Install with skills.sh (any agent)
npx skills add testland/qa --skill risk-matrixrisk-matrix
Overview
Per rbt-wiki (opens in new window):
"Risk-based testing (RBT) is 'a type of software testing that functions as an organizational principle used to prioritize the tests of features and functions in software, based on the risk of failure.'"
The risk matrix is the artifact that drives RBT decisions. Without it, prioritization is gut-feel; with it, the team has a defensible record of "why we tested this and not that."
When to use
How to use
The worked example below runs a checkout release through the full flow. For the adjacent risk artifacts and workflows, see the routing table at the end.
Step 1 - Pick the methodology
Per rbt-wiki (opens in new window), two approaches:
| Approach | Method | When |
|---|---|---|
| Lightweight | Impact × Likelihood, simple high/medium/low | Default; most teams. |
| Heavyweight | FMEA / Cost of Exposure / QFD / FTA | Regulated industries; safety-critical; insurance. |
Most teams should start lightweight - heavyweight methods need specialized expertise.
Step 2 - Lightweight matrix structure
# Risk matrix - `<feature/release>`
**Date:** YYYY-MM-DD **Owner:** _______________ **Reviewers:** _______________
## Risks
| ID | Risk | Category | Impact (1-5) | Likelihood (1-5) | Score | Mitigation | Owner | Due |
|-----|-----------------------------------------------|------------|-------------:|-----------------:|------:|-------------------------------------|-------|-----|
| R-1 | Promo discount math wrong (off-by-cent) | Business | 5 | 3 | 15 | Add property-based tests on rounding | Alice | 2026-05-15 |
| R-2 | Stripe webhook delivery failure not retried | Technical | 4 | 4 | 16 | Add retry + DLQ; add chaos test | Bob | 2026-05-12 |
| R-3 | EU tax calculation incorrect | Regulatory | 5 | 2 | 10 | UAT with finance team | Carol | 2026-05-20 |
| R-4 | Cart loses state on app restart | UX | 3 | 3 | 9 | Persistent cart in localStorage | Dave | 2026-05-10 |
## Heatmap
| Likelihood ↓ \ Impact → | 1 (low) | 2 | 3 | 4 | 5 (high) |
|--------------------------|---------|---|---|---|----------|
| 5 (very likely) | | | | | |
| 4 | | | | R-2 | |
| 3 | | | R-4 | | R-1 |
| 2 | | | | | R-3 |
| 1 | | | | | |
## Verdict
- **Critical (score >=15):** R-1 (15), R-2 (16). Block release until mitigated.
- **High (score 9-14):** R-3 (10), R-4 (9). Mitigate this sprint.
- **Medium (score 5-8):** (none).
- **Low (score 1-4):** (none).The 5×5 matrix yields scores 1-25; the team picks the threshold for "block release" (typically 15+).
Step 3 - Risk categories
Per rbt-wiki (opens in new window), risks span:
Tag every risk with one category. Patterns emerge over time - "all our top risks are integration" suggests an architectural review, not just more testing.
Step 4 - Map risks to test types
A populated matrix drives the test plan:
| Risk class | Recommended test types |
|---|---|
| Business logic | Unit + property-based + UAT |
| Technical | Integration + chaos + load |
| Regulatory | UAT with stakeholder + compliance review |
| UX | Manual exploratory + visual regression |
| Security | Threat model + SAST + DAST + pen test |
| Performance | Load + perf budget + canary |
| Integration | Contract testing + integration tests + canary |
The test plan reads off the matrix: top-N risks → test types per risk → estimated effort.
Worked example - checkout redesign release
Input: the checkout-redesign release scope, lightweight methodology (Step 1).
Intake and score (Steps 2-3). Four risks surface, each tagged with a category and scored impact × likelihood:
| ID | Risk | Category | Impact | Likelihood | Score |
|---|---|---|---|---|---|
| R-1 | Promo discount math wrong (off-by-cent) | Business | 5 | 3 | 15 |
| R-2 | Stripe webhook delivery failure not retried | Technical | 4 | 4 | 16 |
| R-3 | EU tax calculation incorrect | Regulatory | 5 | 2 | 10 |
| R-4 | Cart loses state on app restart | UX | 3 | 3 | 9 |
Tier the verdict (Step 2). With a block threshold of 15: R-2 (16) and R-1 (15) block the release until mitigated; R-3 (10) and R-4 (9) are high and get mitigated this sprint.
Read the test plan off the matrix (Step 4). Each risk's category selects its test types:
Outcome. The two blocking risks (R-1, R-2) get owners and due dates before sign-off; the matrix is committed to docs/risk-matrices/2026-Q2-checkout-redesign.md and re-reviewed at the next cadence point (Step 6).
Step 5 - Heavyweight methods (FMEA, Cost of Exposure)
For regulated or safety-critical products where lightweight scoring is insufficient, risk-based testing offers quantitative methods - FMEA (Risk Priority Number = severity × occurrence × detectability) and Cost of Exposure (annual financial risk vs mitigation cost) - per rbt-wiki (opens in new window). Both need specialized expertise; use them only when regulation or financial justification requires it. Full row structure, worked FMEA and Cost-of-Exposure tables, and a when-to-use guide are in references/heavyweight-risk-scoring.md.
Step 6 - Cadence
| Cadence | Trigger |
|---|---|
| Per-feature | Before development starts |
| Per-release | Pre-release sign-off |
| Quarterly | Strategic risk review |
| Post-incident | Update the matrix with the surfaced risk |
The matrix is a living document - risks change as features ship, mitigations land, and incidents reveal new failure modes.
Step 7 - Format + storage
docs/risk-matrices/
├── 2026-Q2-checkout-redesign.md
├── 2026-Q2-stripe-integration.md
├── 2026-Q1-summary.md ← rollup
└── README.mdMarkdown files version-controlled in git. Reviews via PR; updates tracked over time.
Step 8 - Risk coverage mapping
A risk-coverage matrix proves every meaningful risk has a mitigation that traces to a test or monitor - the risk-side complement to the requirements traceability matrix (traceability-matrix-builder, in the qa-test-management plugin). Per ISTQB CTAL-TM ch. 5 on risk-based test prioritisation and ISO/IEC/IEEE 29119-3:2021 §6.3 on traceability (cite by stable ID). Run it before a release sign-off or compliance audit, at sprint retrospectives to find coverage debt, and in CI per PR.
8a - Ingest the risk register
Pull risks from the release matrix (this skill) and the product register (references/product-risk-register.md); project risks (schedule, staffing) are typically excluded - only product / release risks map to test coverage. Filter to score >= 5 (Medium+).
8b - Inventory coverage from three sources
Tag tests with a risk:<ID> marker in name / docstring / front-matter, then:
grep -r "risk:R-001\|risk:PR-001" tests/ --include="*.py" \
--include="*.js" --include="*.ts" --include="*.java" -l| Coverage source | How to collect |
|---|---|
| Automated tests | Repo scan for risk:<ID> tags (above) |
| Manual test cases | Query the TCM for cases whose refs field contains the risk ID |
| Production monitoring | A risk-coverage.yaml map of risk ID -> monitor IDs (e.g., datadog-monitor://stripe-webhook-failure-rate) |
8c - Compute depth and find orphans
Per risk, coverage depth = linked automated tests + manual cases + monitors:
| Depth | Verdict |
|---|---|
| 0 | Orphan risk - no coverage. Critical if risk score ≥ 10. |
| 1 | Minimal. Acceptable for low-score risks; insufficient for critical. |
| 2-4 | Reasonable. Multiple angles (unit + integration + monitor). |
| 5+ | Possibly over-tested. Audit for redundancy. |
Also run the reverse pass: tests whose risk:<ID> tag points at a retired / non-existent risk are orphan tests - written for risks that no longer exist. Audit for deletion.
8d - Emit the matrix + executive summary
Emit a Markdown document ordered by score descending: a header (total risks, covered count and %, orphan count split critical vs low, average depth), one row per risk (ID, title, score, automated tests, manual cases, monitors, depth - bold any orphan), an "orphan risks (critical action)" section with a recommended action + owner + estimate per orphan, an "over-covered (audit)" list, and a coverage-debt trend table (orphan count and average depth over recent months). Keep both artifacts version-controlled next to the matrix so the trend is real history.
8e - CI gate
Re-build the matrix on every PR; fail if a critical-score risk becomes uncovered:
- name: Risk coverage check
run: |
python scripts/build-risk-coverage.py \
--risks risks.yaml \
--output risk-coverage.md \
--fail-on-orphan-score 15Caveats: tag discipline is the ceiling (untagged tests under-report coverage); depth measures count, not test quality; a monitor existing does not prove it would catch the risk; treat depth 1 as "covered" only for low-score risks.
Going deeper (referenced guides)
| Task | Guide |
|---|---|
| Long-lived product-quality risks (persist across releases, ISO 25010 walk) | references/product-risk-register.md |
| Project-execution risks (schedule, staffing, vendor; Avoid / Mitigate / Transfer / Accept) | references/project-risk-register.md |
| Facilitating the risk-storming session that fills the matrix | references/risk-storming.md |
| Calibrating an aged matrix against observed defects, escapes, and churn | references/calibration.md |
| Auditing a register's assessment quality before release planning | references/risk-review-checklist.md |
| FMEA / Cost-of-Exposure worked tables | references/heavyweight-risk-scoring.md |
Anti-patterns
| Anti-pattern | Why it fails | Fix |
|---|---|---|
| Risk matrix authored once, never updated | Becomes irrelevant; team stops trusting. | Per-feature + quarterly cadence (Step 6). |
| Subjective scoring without examples | Different reviewers score differently; matrix unreliable. | Document score rubric (e.g., "5 = customer money loss"). |
| All-business-category matrix | Misses technical / regulatory risks; gaps invisible. | Tag every risk with a category (Step 3). |
| Matrix without owner per row | "Mitigated" never happens. | Owner column required (Step 2). |
| Heavyweight FMEA on a small product | Over-engineering; team disables. | Lightweight default; FMEA only when regulation requires (Step 1). |
| Risk matrix in slides, not version-controlled | History lost; rollup impossible. | Markdown + git (Step 7). |
Limitations
References
Risk-matrix calibration
View source (opens in new window)Risk-matrix calibration
Deep reference for the risk-matrix SKILL.md. Checks an already-written matrix against what actually happened: maps each row's likelihood rating to observed defect density, test failure rate and code churn, maps its impact rating to the severity mix and escape rate, then classifies each row as over-stated, under-stated, in-agreement, or not calibrated. Every proposed rating change carries the observation that produced it, and every proposal is handed to the matrix owner rather than applied.
Use when a matrix has been driving test decisions for at least three releases and nobody has yet checked whether its ratings match the defects, escapes and incidents that followed.
What calibration answers
A risk matrix records what a team believed, at authoring time, about how likely each area is to fail and how bad that failure would be. Risk-based testing is defined by ISTQB as "a test approach in which the management, selection, prioritization, and use of test activities and resources are based on corresponding risk types and risk levels" (https://glossary.istqb.org/en_US/term/risk-based-testing), so those ratings directly control where test effort goes. Lightweight risk assessment scores a row on two factors, likelihood and impact (https://en.wikipedia.org/wiki/Risk-based_testing).
Calibration asks one question: over the window that has since elapsed, did the things the matrix said were likely and severe actually turn out to be likely and severe? The output is a set of proposed rating changes, each attached to the observation that produced it, for the matrix owner to accept or reject.
Scope boundary
This is the after-the-fact check, not the authoring pass. The axis is already-written ratings versus observed outcomes.
| In scope here | Out of scope here |
|---|---|
| Choosing which observed signal corresponds to each matrix dimension | Choosing lightweight versus heavyweight methodology |
| Turning observations into a comparable rating on the matrix's own scale | Designing the matrix columns, heatmap or banding |
| Deciding whether a difference is large enough to report | Picking the risk category taxonomy |
| Wording a proposed change so the owner can audit it | Deciding which test types a risk maps to |
| Surfacing areas absent from the matrix that the defect data insists on | FMEA severity / occurrence / detectability scoring |
| Naming the evidence gaps that leave a row uncalibratable | Review cadence, file layout, version control |
If the matrix does not yet exist, or its rows have no consistent feature column and no consistent score format, there is nothing here to calibrate against. Author or restructure it first, per the SKILL.md spine.
Calibration is also not prediction. It reports what was observed in a closed historical window. It does not forecast next quarter's defects, and it does not fit a model. That restraint is deliberate: only 19.9% of teams surveyed in the PractiTest State of Testing 2026 report use AI for risk identification, against 70% for test case creation (https://www.practitest.com/state-of-testing/), and unsourced predictive scoring at the decision layer is exactly what that gap is made of.
Before anything else: what defect data can and cannot tell you
Observed defect data is a lagging and biased signal, and calibration is only as good as that signal. Read this section before running any of the steps below, because it changes what the numbers are allowed to conclude.
You only see defects in code that was tested and used. A row with zero defects in the window has at least three possible explanations:
No amount of defect data distinguishes these three. Absence of evidence in a defect tracker is not evidence of low likelihood. The practical rule that follows is in Step 3: a zero-defect row is never grounds for lowering a likelihood rating on its own. It is grounds for asking which of the three explanations applies, and reporting the answer.
Two further biases are worth naming explicitly:
State these limits in the report itself, not only here. A reader who does not know the data is biased will read a proposed downgrade as a fact.
Step 1 - Map each matrix dimension to observed signals
Each of the two rating dimensions gets its own set of observed signals. Use more than one signal per dimension so that a single weak measurement cannot move a rating on its own.
| Matrix dimension | Primary observed signal | Corroborating signals |
|---|---|---|
| Likelihood | Defect density for the row's source paths, meaning "the number of defects per unit size of a work product" (https://glossary.istqb.org/en_US/term/defect-density) | Failure rate of the tests that cover the row over the window; code churn for the same paths |
| Impact | Severity mix of the row's defects, typically the share at the team's top two severity levels | Escape rate, meaning the share of the row's defects that were "not detected by a test activity that is supposed to find it" (https://glossary.istqb.org/en_US/term/escaped-defect); incident or SLO-breach correlation where the team records it |
Two rules on density and churn
The published results behind both rules (Nagappan and Ball; Zimmermann et al.), with their caveats, are in the Empirical basis section below.
Step 2 - Convert observations into an observed rating
Produce an observed likelihood and an observed impact on the same 1 to 5 scale the matrix already uses. Do not invent a new scale, and do not normalise across teams: severity labels mean different things in different trackers, so a calibration is valid only inside the conventions of the tracker it read.
The team's own authoring rubric supplies the cut points. If the matrix says likelihood 4 means "expected to fail in most releases", express the observed density in those terms rather than in a generic band. Where the matrix has no written rubric, say so in the report and mark every proposed change as provisional, because without a rubric the comparison is between one person's judgement and another's.
Record, for each row, all of:
That last item is the honesty control. A row whose observed rating rests on two defects is a rating with a wide error bar, and the report should show the count so a reader can discount it.
Step 3 - Decide whether a divergence is worth reporting
Most rows will differ from their observations by a little. Reporting those differences buries the ones that matter and trains the owner to skim the report.
Reporting thresholds
These are practitioner conventions, not standards. No published standard sets them. The reasoning for each cut is given so a team can move it with its eyes open.
| Threshold | Convention | Why this cut |
|---|---|---|
| Per-dimension difference | Report at 2 or more points on a 1 to 5 scale | One point is inside the spread two people produce scoring the same row independently, which is a known weakness of subjective scoring. Two points is the smallest gap that is unlikely to be scorer noise. |
| Combined score difference | Report at 4 or more points of likelihood times impact | Under a common 5x5 banding (low 1-4, medium 5-8, high 9-14, critical 15 and up) the narrowest band is four points wide, so a smaller change cannot by itself move a row out of its band, and a change that does not move the band does not change any decision. |
| Minimum window | At least 3 releases, or one quarter, whichever is longer | A single release usually yields a single-digit defect count per row, and single-digit counts move by 100% on one incident. Below this the observation has less authority than the authoring judgement it would overturn. |
| Minimum defect count per row | State the count; treat fewer than 5 defects as directional only | Below roughly five events, a rating change is being driven by individual incidents rather than by a rate. |
Rows that clear a threshold fall into one of three classifications.
3.1 Over-stated
The matrix rates the row higher than the observations support.
Report it as over-stated only after ruling out the three explanations in the biased-data section above. Specifically:
3.2 Under-stated
The matrix rates the row lower than the observations support. This is the finding calibration exists to produce, and it is the one least vulnerable to the absence-of-evidence problem: defects that happened, happened.
Strengthen it with corroboration. An under-stated finding is strongest when defect density, test failure rate and escape rate all point the same way, and weakest when only churn does.
3.3 Coverage gap
An area that the defect data keeps naming has no row in the matrix at all, or has a row whose observations cannot be computed.
Two sub-cases, and they get different wording:
Step 4 - Every proposed change cites its observation
A rating change is a proposal for a human to accept, never an automatic edit. The matrix is a team artifact, usually version controlled and usually owned by a named person. Calibration produces a diff for review, and stops there.
The rule that makes review possible: every dimension of every proposed change names the observation behind it. Not a summary of the observation, a citation of it, precise enough that the owner can re-run the same query and see the same number.
A citation is adequate when it carries all four of:
A proposed change missing any of the four is not reportable. A reviewer who cannot check the number is being asked to trust a black box, and a black box that edits the team's risk ratings is worse than no calibration at all.
Step 5 - Candidate new entries
Areas absent from the matrix that the defect data insists on are output as candidates, listed with their supporting observations and a suggested starting rating. They are never added automatically. The matrix owner decides whether the area deserves its own row or belongs inside an existing one, and that decision is about how the team models its own system, not about the data.
Two entry conditions, both practitioner conventions and both self-calibrating to the team's own data rather than to an absolute number:
Self-calibrating conditions are preferred here because an absolute cut (say, "5 or more defects") means something different for a two-person project and a two-hundred-person one.
For each candidate, propose a starting likelihood and impact, and say plainly which half of the proposal is weaker. Impact is usually the weaker half: defect data shows what broke, not what the breakage cost the user, and that translation is a product judgement.
Empirical basis for the signals
The published results behind the "churn corroborates only" and "no imported coefficient" rules, with the caveats that keep each result honest.
Why density and not raw count
A raw defect count conflates "small area, few defects" with "stable area, few defects". Normalising by size, per the ISTQB defect-density definition (opens in new window), makes rows comparable to each other. Where lines of code are a poor size proxy (heavy generated code, config-driven modules), normalise by number of changes to the same paths instead, and say in the report which denominator you used.
How much weight churn deserves
Churn is a corroborating signal, never the primary evidence for a rating change. The published relationship is real but narrow: Nagappan and Ball showed that "while absolute measures of code churn are poor predictors of defect density, our set of relative measures of code churn is highly predictive of defect density", with a metric suite that discriminated fault-prone from non-fault-prone binaries "with an accuracy of 89.0 percent" (ICSE 2005, https://www.microsoft.com/en-us/research/publication/use-of-relative-code-churn-measures-to-predict-system-defect-density/, record at https://openalex.org/W2100945416). Three limits on that result matter:
Why labelled bug-fix data is biased
Bird et al., examining bug-fix datasets across several projects, found that only a fraction of bug fixes are labelled in version histories and reported "strong evidence of systematic bias" in the resulting datasets, which threatens both prediction models built on them and hypotheses tested with them (ESEC/FSE 2009, https://www.cs.ucdavis.edu/~filkov/papers/biasbusters.pdf, record at https://www.microsoft.com/en-us/research/publication/fair-and-balanced-bias-in-bug-fix-datasets/). If your team labels defects by component inconsistently, the calibration inherits that inconsistency.
Worked example
The expected output shape end to end: a summary, under-stated and over-stated findings with every dimension citing value / source / window / event count, not-calibrated rows, candidate new entries, and the "what was not done" footer. Names and numbers are illustrative.
# Risk-matrix calibration - checkout matrix
Window: 2026-02-01 to 2026-04-30 (3 releases). Density denominator: defects per 1k LOC.
## How to read this
Proposals only. Nothing in the matrix has been changed. Defect data is lagging
and biased: a quiet row may be sound, untested, or unused, and this report
cannot tell those apart. Rows marked "not calibrated" are gaps in the
evidence, not low risk.
## Summary
| Outcome | Rows |
|---|---|
| In agreement (below threshold) | 14 |
| Under-stated | 4 |
| Over-stated | 2 |
| Not calibrated (unmeasurable) | 3 |
| Candidate new entries | 1 |
## Under-stated
### R-12 inventory-cache: propose likelihood 2 -> 4, impact 3 -> 4 (score 6 -> 16)
| Dimension | Matrix | Observed | Observation cited |
|---|---|---|---|
| Likelihood | 2 | 4 | 13 defects over 8.4k LOC = 1.55 per 1k LOC, against a matrix-wide median of 0.31. Source: tracker export 2026-Q2, component = inventory-cache. Window: full. Events: 13. |
| Impact | 3 | 4 | 6 of 13 at severity S1 or S2 (46%); 4 of 13 escaped to production (31%), against a matrix-wide escape rate of 11%. Source: same export, field found_in. Events: 13. |
| Test failure rate (corroborating) | n/a | 6% | Suite covering services/inventory/cache fell from 99% to 94% pass rate across the window. Source: CI results 2026-Q2. Events: 412 runs. |
| Churn (corroborating only) | n/a | high | 47 commits to services/inventory/cache over 89 days, normalised 5.6 commits per 1k LOC, top decile of the repo. Corroborating only, not causal. |
All four citations carry value, source, window and event count. 13 events is
above the 5-event floor, so this is reported as a rate, not as directional.
## Over-stated
### R-03 payments-provider-fallback: propose likelihood 4 -> 2, impact unchanged at 5 (score 20 -> 10)
| Dimension | Matrix | Observed | Observation cited |
|---|---|---|---|
| Likelihood | 4 | 2 | 1 defect over 6.1k LOC = 0.16 per 1k LOC. Source: tracker export 2026-Q2, component = payments-fallback. Events: 1. |
| Impact | 5 | 5 | Single defect at S1. Too few events to move impact. Events: 1. |
**Event count is 1.** Directional only, below the 5-event floor.
Ruled out before proposing: the row is covered (214 test executions in the
window) and exercised (fallback path invoked 1,190 times in production), so
this is not a coverage or exposure artefact. **Open point for the owner:** the
high rating may be a precaution that is currently working, and lowering it
would reduce the testing that keeps it quiet. This report cannot settle that.
## Not calibrated
| Row | Missing input |
|---|---|
| R-08 legacy-tax-import | No source paths recorded; defects cannot be attributed. |
| R-15 partner-sftp-drop | Tracker component field empty on 22 of 24 defects. |
| R-21 admin-audit-log | No automated tests cover the row; failure-rate signal unavailable. |
These are evidence gaps. Do not read them as low risk.
## Candidate new entries
### notifications-webhook-retry (no row in matrix)
| Signal | Value | Observation cited |
|---|---|---|
| Defects | 8 | Tracker export 2026-Q2, component = notifications-webhook. Window: full. |
| Density | 0.94 per 1k LOC | 8 defects over 8.5k LOC; matrix-wide median 0.31. Entry condition met: above median row. |
| Escapes | 2 of 8 (25%) | Field found_in = production. Entry condition met: at least one escape. |
| Severity mix | 3 S1, 2 S2, 3 S3 | Same export. |
Suggested starting rating: likelihood 3, impact 4. **The impact half is the
weaker one**: escape rate is high, but what a missed webhook costs depends on
subscriber retry behaviour, which is a product judgement this report cannot make.
## What was not done
No matrix row was edited. No test selection was re-run. No forecast was made.Anti-patterns
| Anti-pattern | Why it fails | Fix |
|---|---|---|
| Treating "no defects in the window" as evidence for likelihood 1 | Could equally mean untested or unused. The data cannot distinguish the three. | Cross-check test executions and production usage first; if either is near zero, report a coverage or exposure gap instead (Step 3.1). |
| Ranking rows by raw defect count | Conflates a small busy area with a large stable one. | Normalise to defect density per the ISTQB definition (https://glossary.istqb.org/en_US/term/defect-density) and state the denominator. |
| Leading a rating change with churn | Churn is a correlate of where work happens, not a cause of defects, and only relative churn predicted anything in the published result. | Lead with defect density and severity mix; use churn to corroborate a direction only (Step 1). |
| Importing a published defect-prediction coefficient | Cross-project transfer fails even within the same domain and process (https://api.openalex.org/works/doi:10.1145/1595696.1595713). | Calibrate against the team's own history using the team's own rubric. |
| Reporting every difference | One-point differences are scorer noise; a full report of them buries the real findings. | Apply the Step 3 thresholds and say in the report that they are conventions. |
| Editing the matrix directly | The matrix is a team artifact with an owner; a silent edit destroys the record of who believed what and when. | Emit proposals; the owner applies them (Step 4). |
| A proposed change with a bare number and no source | The reviewer cannot re-derive it, so the ask is unauditable. | Every dimension carries value, source, window and event count (Step 4). |
| Auto-adding candidate entries | Whether an area deserves its own row is a modelling decision about the system, not a data question. | Surface candidates with observations and a suggested rating; the owner decides (Step 5). |
| Extending the report into a forecast | The window is closed history; projecting from it is a different technique with different error properties, and unsourced prediction is what erodes trust in the whole exercise. | Report observed divergence only. |
| Comparing severity across teams | Severity labels are local conventions; an S1 in one tracker is an S2 in another. | Calibrate within one tracker's conventions and say so. |
Limitations
Heavyweight risk scoring: FMEA and Cost of Exposure
View source (opens in new window)Heavyweight risk scoring: FMEA and Cost of Exposure
Deep reference for the risk-matrix SKILL.md. Use when the default lightweight impact-by-likelihood matrix (Step 1) is insufficient - regulated industries, safety-critical systems, or when test budget must be justified in financial terms to non-technical stakeholders.
Both methods are the heavyweight branch of risk-based testing per Risk-based testing (Wikipedia) (opens in new window), which names FMEA, Cost of Exposure, QFD, and FTA as the quantitative alternatives to lightweight scoring and describes them as tools for "financial impact analysis". They need specialized expertise; reach for them only when regulation or a money-based mitigate-or-accept decision requires it.
FMEA (Failure Mode and Effect Analysis)
Per row: failure mode + effect + severity (1-10) + occurrence (1-10) + detectability (1-10) → RPN (Risk Priority Number = S × O × D, range 1-1000).
| ID | Failure mode | Effect | S | O | D | RPN | Action |
|-----|--------------------------------|-----------------------------------|----|---|---|-----|--------|
| F-1 | Promo math wrong | Wrong charge to customer | 8 | 5 | 4 | 160 | property tests |
| F-2 | Stripe webhook missed | Order not fulfilled | 9 | 4 | 6 | 216 | retry + DLQ + monitor |Detectability is the inverse of "tests would catch it" - high D = hard to catch = high RPN. Two rows with equal severity and occurrence rank differently purely on how visible the failure is to existing checks.
Cost of Exposure
Quantify the annual financial risk and weigh it against the one-time plus recurring mitigation cost:
Risk: Stripe webhook delivery failure
- Estimated incidents per year (untreated): 12
- Average revenue lost per incident: $5,000
- Annual cost of exposure: $60,000
- Cost of mitigation (retry + DLQ + monitor): $15,000 one-time + $2,000/year
- Decision: Mitigate (ROI in 3 months)Cost of Exposure turns "this is risky" into a budget line a finance stakeholder can approve or reject.
When each applies
| Method | Reach for it when |
|---|---|
| FMEA | A regulated or safety-critical product needs a defensible, reproducible ranking with a detectability dimension the lightweight 5x5 lacks. |
| Cost of Exposure | Test budget must be justified in money, or the mitigate-or-accept decision hinges on ROI rather than a score threshold. |
Product risk register
View source (opens in new window)Product risk register
Deep reference for the risk-matrix SKILL.md. The product-level register variant: long-lived product-quality risks (functionality, performance, security, usability, compatibility, reliability) that persist across releases, distinct from the per-release matrix the spine builds. Both feed risk-based test selection and planning.
Per ISTQB CTAL-TM syllabus chapter 5 on risk-based testing and ISO 31000:2018 (risk management) - cite by stable ID; ISO behind paywall.
When to build one
Step 1 - Identify risks by quality characteristic
Walk through ISO 25010 quality characteristics. For each, ask: "What could go wrong here in this product?"
| Characteristic | Example product risks |
|---|---|
| Functional suitability | Core business logic incorrectness (pricing, tax, compliance calculations) |
| Performance efficiency | Sustained load failure; large-dataset slowness; cold-start latency |
| Compatibility | Browser / OS / device fragmentation; third-party API drift |
| Usability | Accessibility (WCAG conformance); learnability for new users; error messaging |
| Reliability | Recovery from upstream failures; data durability; transactional integrity |
| Security | Auth / authz; PII exposure; injection vulnerabilities; supply chain |
| Maintainability | Tech debt accumulating in critical paths; test brittleness |
| Portability | Migration between cloud providers; export/import data integrity |
Per ISO/IEC 25010:2023 quality model (cite by stable ID).
Aim for 15-30 product-level risks. Fewer than 10 = too sparse; more than 50 = mix with per-release risks.
Step 2 - Score per impact × likelihood
Use the same 1-5 scale as the spine's matrix. Score is impact × likelihood:
| Score | Tier | Action |
|---|---|---|
| 15-25 | Critical | Continuous monitoring + multiple mitigations + quarterly review |
| 10-14 | High | At least one strong mitigation + annual review |
| 5-9 | Medium | Documented mitigation strategy + biannual review |
| 1-4 | Low | Acknowledged; mitigation optional |
Step 3 - Document the register
# Product risk register - <product-name>
**Last reviewed:** YYYY-MM-DD **Owner:** <name> **Next review:** YYYY-MM-DD
## Active risks (n=22)
| ID | Category (ISO 25010) | Risk | Impact | Likelihood | Score | Mitigation(s) | Owner | Last review |
|---|---|---|---:|---:|---:|---|---|---|
| PR-001 | Functional suitability | Pricing engine off-by-cent in EU markets | 5 | 3 | 15 | Property-based testing on rounding; nightly compliance test suite | Alice | 2026-05-01 |
| PR-002 | Security | OAuth refresh-token leak via logs | 5 | 2 | 10 | Log redaction middleware; quarterly secret-scan; presidio-pii-detection in CI | Bob | 2026-04-15 |
| PR-003 | Reliability | Stripe webhook delivery failure not retried | 4 | 4 | 16 | DLQ + retry; chaos test in staging weekly | Carol | 2026-05-10 |
| PR-004 | Performance | Catalog search slows under >10k SKUs | 4 | 3 | 12 | Elasticsearch tuning; k6 load test gate | Dan | 2026-03-20 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... |
## Retired risks (n=5)
| ID | Risk | Retired date | Why retired |
|---|---|---|---|
| PR-R-001 | Legacy SOAP API maintenance | 2026-02-01 | API decommissioned in v3.0 |
| ... | ... | ... | ... |Step 4 - Link mitigations to test coverage
For each active risk, name at least one mitigation and link it to existing test coverage (or flag a gap):
| PR-001 | Pricing engine off-by-cent | 15 | Tests: tests/billing/test_promo_stacking.py + nightly compliance suite (PROJ-T123 + 124) | Alice |Use the risk coverage mapping workflow in SKILL.md to generate the test-to-risk map.
Step 5 - Quarterly review
Per ISTQB CTAL-TM, product risks should be re-scored at least quarterly:
## Q2 2026 review log
- **PR-001**: Impact unchanged (5); likelihood **lowered 3 → 2**
(property-based tests in place + 6 months no incidents). New
score: 10 (was 15).
- **PR-003**: Impact unchanged (4); likelihood **raised 4 → 5**
after Q1 webhook outage at provider. New score: 20 (was 16).
- **PR-007**: **Retired** - feature deprecated in v3.0.
- **New: PR-022**: Locale-related date formatting; impact 3,
likelihood 3, score 9. Owner: Eve.
Net change: 1 new, 1 retired, 1 risen, 1 lowered. Total active: 22.Step 6 - Seed the release matrix
When a release matrix starts:
Worked example - e-commerce product
A 24-risk register might decompose like:
| Category | Count | Avg score |
|---|---|---|
| Functional suitability | 6 | 13 |
| Performance | 3 | 11 |
| Security | 5 | 14 |
| Reliability | 4 | 12 |
| Compatibility | 3 | 9 |
| Usability | 2 | 8 |
| Maintainability | 1 | 6 |
Distribution suggests Security + Functional suitability are the top areas to invest in.
Anti-patterns
| Anti-pattern | Why it fails | Fix |
|---|---|---|
| One-time creation, never reviewed | Register becomes stale | Quarterly review cadence |
| Mixing per-release risks into the product register | Confuses long-lived from transient | Per-release risks in the release matrix; product-level here |
| No retired-risks section | History lost; "why did we stop testing X?" unanswered | Always keep a retired-risks log |
| Score without recent re-review | Stale scores misinform planning | "Last review" date column; auto-flag stale entries |
| Mitigation missing test coverage link | Mitigation is theoretical; no evidence it works | Always link mitigation → test (or flag as gap) |
| ISO 25010 categories unused | Risk list skewed to functional only | Walk all 8 characteristics |
| Risk register in a wiki page that nobody opens | Effectively shelf-ware | Versioned in repo; reviewed at sprint planning |
Limitations
References
Project risk register
View source (opens in new window)Project risk register
Deep reference for the risk-matrix SKILL.md. The project-level register variant: risks to project execution (schedule slippage, environment instability, people / staffing, vendor / dependency, scope creep) rather than the product itself. The project manager reviews it weekly.
Per ISTQB CTAL-TM, the distinction is:
Cite ISTQB glossary (glossary.istqb.org (opens in new window)) "product risk" + "project risk". Project risks are typically excluded from the risk-to-test-coverage matrix (SKILL.md coverage mapping section): only product / release risks map to test coverage.
When to build one
Step 1 - Identify by category
Per ISO 31000:2018 (cite by stable ID) and PMI PMBOK 7th edition risk categorisation, project risks fall into broad buckets:
| Category | Example risks |
|---|---|
| Schedule | Estimate uncertainty; downstream dependency slippage; holiday / OOO clashes |
| People / staffing | Key engineer leaves; on-call rotation under-staffed; specialist knowledge concentrated |
| Scope | Scope creep mid-sprint; spec ambiguity; stakeholder mid-flight changes |
| Environment / infrastructure | Staging environment broken; CI / test infrastructure outage |
| Vendor / third-party | API deprecation by vendor; vendor SLA breach; cloud-provider regional outage |
| Compliance / regulatory | Audit deadline missed; new regulation in flight (e.g., GDPR, SOC 2) |
| Budget | Cloud-spend overrun; tool licensing surprise |
| Communication | Cross-team alignment failures; missing stakeholder sign-off |
Aim for 8-20 active project risks at any time. Stale entries get retired.
Step 2 - Score per impact × likelihood
Impact 1-5:
1 = Minor delay / inconvenience
2 = Multi-day delay; small re-work
3 = Sprint slippage; significant re-work
4 = Release slippage; major re-plan
5 = Quarter slippage; reputation / financial damage
Likelihood 1-5:
1 = Very unlikely (<10% in horizon)
2 = Unlikely (~25%)
3 = Possible (~50%)
4 = Likely (~75%)
5 = Very likely (>90%)
Score = Impact × Likelihood (range 1-25)Step 3 - Pick a mitigation strategy
Per ISO 31000:2018, four standard responses:
| Strategy | When | Example |
|---|---|---|
| Avoid | Risk is so high that the project scope is reshaped to remove it | Decline a Q4 launch that requires a known-fragile dependency |
| Mitigate | Reduce likelihood or impact via active intervention | Add a staging-mirror to reduce dependency-outage risk |
| Transfer | Shift the risk via contract / insurance / outsourcing | Vendor contract clause for SLA breach; insurance policy |
| Accept | Document + monitor; act when (if) it triggers | Note a Q1 holiday-staffing risk; OOO calendar visible |
Document the chosen strategy per risk.
Step 4 - Document the register
# Project risk register - <project / quarter>
**Last reviewed:** YYYY-MM-DD **Owner:** <PM> **Next review:** YYYY-MM-DD
## Active risks (n=11)
| ID | Category | Risk | Impact | Likelihood | Score | Strategy | Mitigation | Owner | Status |
|---|---|---|---:|---:|---:|---|---|---|---|
| PJ-001 | Schedule | Q2 launch depends on Stripe migration; Stripe rate-limits doc work | 4 | 3 | 12 | Mitigate | Run migration in parallel with team-2 work | Alice | Active |
| PJ-002 | People | Senior payments engineer on parental leave Q2 | 4 | 5 | 20 | Mitigate | Knowledge-transfer sessions Q1; pair-coding | Bob | Active |
| PJ-003 | Vendor | Auth0 deprecating legacy SDK Q3 | 3 | 5 | 15 | Mitigate | Migrate to new SDK Q2 (1 sprint allocated) | Carol | Active |
| PJ-004 | Compliance | SOC 2 Type II audit Q3 - controls evidence collection backlog | 5 | 3 | 15 | Mitigate | Hire compliance contractor; start collection Q1 | Dan | Active |
| PJ-005 | Environment | Staging cluster autoscale unreliable | 3 | 4 | 12 | Mitigate | Migrate staging to k8s-autopilot Q2 | Eve | Active |
| PJ-006 | Scope | "AI feature" spec drifting in stakeholder reviews | 3 | 4 | 12 | Mitigate | Lock spec by end Q1; weekly stakeholder review | Fran | Active |
| PJ-007 | Schedule | Cyber-week launch window non-negotiable | 5 | 2 | 10 | Mitigate + Accept | Buffer + war-room ready | Alice | Active |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
## Retired / triggered risks (n=4)
| ID | Risk | Outcome | Lessons |
|---|---|---|---|
| PJ-R-001 | DB migration vendor delay | Triggered Q1; mitigated by parallel path | Two-vendor strategy works |
| PJ-R-002 | Staffing - onboarding lag | Not triggered | Mitigation (early hire) effective |Step 5 - Weekly review cadence
Project risks evolve fast. Weekly review at standup or PM syncpoint:
## Week of YYYY-MM-DD review
- **PJ-002** (key engineer leave): KT session 3/4 complete. Score
unchanged.
- **PJ-003** (Auth0 SDK): migration started; likelihood drops 5 → 3.
New score: 9 (was 15).
- **New PJ-012**: Cloud provider regional outage (us-east-1) on
YYYY-MM-DD reminded us of single-region risk. Impact 4,
likelihood 2, score 8. Strategy: monitor.
- **Triggered PJ-007** (Cyber-week launch): launched successfully;
retire.Step 6 - Escalation triggers
Risks scoring ≥15 trigger escalation:
## Escalations this week
- **PJ-002** (score 20): Engineering Director informed.
Mitigation status: 3/4 KT sessions held; remaining pair-coding
blocked on engineer availability.Worked example - quarterly project risk distribution
For a 12-risk register in a Q2 release:
| Category | Count | Avg score | Highest |
|---|---|---|---|
| Schedule | 3 | 13 | 16 |
| People | 2 | 16 | 20 |
| Vendor | 2 | 12 | 15 |
| Scope | 2 | 11 | 12 |
| Environment | 2 | 10 | 12 |
| Compliance | 1 | 15 | 15 |
People + Schedule are dominant - staffing + dependency mitigations need most attention.
Anti-patterns
| Anti-pattern | Why it fails | Fix |
|---|---|---|
| Mixing project + product risks in one register | Confuses risk-response strategies | Separate registers; this for project, product-risk-register.md (opens in new window) for product |
| "Mitigate" is the only strategy | "Accept" is legitimate; not every risk needs an action | Use all 4 strategies (Avoid / Mitigate / Transfer / Accept) |
| Weekly review skipped during crunch | Risks compound when ignored | Hold review even briefly; stale register is worse than no register |
| No retired-risks log | Lose lessons learned | Always keep retired list |
| Score 25 without escalation | Owner alone can't manage critical risks | Escalation rule per Step 6 |
| Mitigation without owner | Risk floats; no one accountable | Always name an owner |
| Status column missing | Can't tell if mitigation is on track | "Active / In progress / Mitigated / Triggered / Retired" status |
Limitations
References
Risk-register review checklist
View source (opens in new window)Risk-register review checklist
Deep reference for the risk-matrix SKILL.md. A hygiene checklist for auditing a risk register (per-release matrix or product register) for assessment quality before release planning or a quarterly review. Blocks substandard risk assessments from driving release planning.
Inputs: the register under review, optionally the coverage matrix from the SKILL.md coverage mapping section, and the decisions folder for accepted risks. Output: per-risk findings + a single register-level verdict (pass / block / pass-with-caveats).
Check 1 - Field completeness
Every entry must have:
| Field | Required? | BLOCK if missing? |
|---|---|---|
| ID | ✓ | ✓ |
| Risk title | ✓ | ✓ |
| Category | ✓ | ✓ |
| Impact (1-5) | ✓ | ✓ |
| Likelihood (1-5) | ✓ | ✓ |
| Score | ✓ | ✓ (computed = I × L) |
| Strategy (Avoid / Mitigate / Transfer / Accept) | ✓ | ✓ |
| Mitigation OR decision link | ✓ | ✓ |
| Owner | ✓ | ✓ |
| Last review date | ✓ | ✓ |
Check 2 - Independence of impact and likelihood
Impact + likelihood must be independently scored, not auto-equated:
def check_independence(risks):
issues = []
pairs = [(r["impact"], r["likelihood"]) for r in risks]
diag_count = sum(1 for i, l in pairs if i == l)
if len(pairs) > 5 and diag_count / len(pairs) > 0.7:
issues.append(
f"{diag_count}/{len(pairs)} risks have impact == likelihood. "
"Likely auto-equated; force independent scoring."
)
return issuesIf >70% of risks have impact == likelihood, the register is suspect (the same principle as scoring defect severity and priority independently).
Check 3 - Strategy discipline
For each "Accept" decision, verify a written acceptance-decision memo exists (who accepted, what evidence, expiry / revisit date). Any Accept without a linked decision document = BLOCK.
For each "Transfer" decision, verify the receiving party (insurance / vendor / SLA) is named. Without it, "Transfer" is hand-wave Accept.
Check 4 - Mitigation-to-coverage linkage
Build the coverage matrix per the SKILL.md coverage mapping section, then:
orphans_critical = [r for r in matrix if r["coverage_depth"] == 0 and r["score"] >= 15]
orphans_high = [r for r in matrix if r["coverage_depth"] == 0 and 10 <= r["score"] < 15]Check 5 - Escalation evidence
Risks scoring ≥15 must have escalation evidence:
| Score | Required escalation |
|---|---|
| 15-19 | Engineering director or equivalent named in owner / reviewer field |
| 20-25 | VP / CTO / CISO sign-off recorded in review log |
Without it, the register has under-escalated risks = caveat.
Check 6 - Review cadence
Per the register type:
| Register | Cadence | Stale after |
|---|---|---|
| Per-release matrix (SKILL.md) | Weekly during sprint | 14 days |
| Product register (product-risk-register.md (opens in new window)) | Quarterly | 100 days |
| Project register (project-risk-register.md (opens in new window)) | Weekly | 14 days |
If most entries' last_review is older than the threshold, the register is stale.
Check 7 - Verdict + report
# Risk-register audit - Q2 2026 release matrix - YYYY-MM-DD
**Risks audited:** 27 active + 4 retired
**Findings:** 6 critical, 9 warnings
**Verdict:** BLOCK - 3 critical findings require fix before release
## Critical (must fix before release planning)
| # | Risk ID | Finding |
|---|---|---|
| 1 | R-14 | Strategy "Accept" without linked decision document |
| 2 | R-22 | Score 20 (impact 5 × likelihood 4); coverage depth 0 (ORPHAN). No test, no monitor, no decision. |
| 3 | PR-009 | Score 16; last review 137 days ago (stale for product register; threshold 100 d) |
## Warnings
| Risk ID | Finding |
|---|---|
| R-08 | impact 3 = likelihood 3 = score 9; pattern repeats for 19/27 entries - likely auto-equated |
| PR-003 | Strategy "Transfer" but recipient not named |
| R-11 | Owner field empty |
| ... | ... |
## Coverage integration
- 4 of 27 risks are orphan (no coverage). Of these:
- 2 critical (score ≥15) - BLOCK above
- 2 low (score <10) - info
## Acceptance decisions integration
- 3 Accept decisions found. 2 have linked documents (R-08, R-12);
1 missing (R-14 - BLOCK above)
## Review cadence
- Average `last_review`: 18 days
- Stale entries (>14 days for release matrix): 7 of 27
- Most-stale: PR-009 at 137 days
## Action items
1. **R-14**: Either author the acceptance decision memo or change
strategy to Mitigate / Transfer.
2. **R-22**: Add at least one mitigation + one test before release.
3. **PR-009**: Re-review now; update `last_review` date.
After fixes, re-run this checklist.Never-pass rules
A register review never returns "pass" when any of these hold:
The review reports and recommends; it never auto-fixes register fields.
Anti-patterns
| Anti-pattern | Why it fails | Fix |
|---|---|---|
| Auditing only critical-score orphans | Medium-score risks accumulate coverage debt | Run all 7 checks |
| Treating "Accept" as default for inconvenient risks | Decision discipline collapses | Require documented decisions per acceptance |
| Skipping the independence check | Auto-equated scores produce misleading priorities | Always run Check 2 |
| Auditing once per release only | Risks drift between release cycles | Audit weekly for release matrices |
| Score thresholds different per team | Cross-team metrics meaningless | Standardise the threshold table; audit against it |
| Reviewers in owner column for "accountability" | Owner ≠ reviewer; concentrates blame | Distinguish owner from reviewer fields |
Limitations
References
Risk storming - facilitation guide
View source (opens in new window)Risk storming - facilitation guide
Deep reference for the risk-matrix SKILL.md. How to plan and facilitate the risk-storming session that fills the matrix: meeting structure, participant roster, per-category brainstorm prompts, affinity grouping, impact × likelihood scoring, and mitigation assignment.
Risk-storming is a collaborative exercise where the team brainstorms what could go wrong with a feature or release. The output feeds directly into the risk matrix (per SKILL.md Step 2). The format originates from threat modeling exercises (notably Adam Shostack's Threat Modeling: Designing for Security) and Gojko Adzic's risk-driven testing community, adapted as a general QA technique.
When to run a session
Session at a glance
Step 1 - Pre-session setup
Schedule 60-90 min. Invite:
Pre-distribute:
Step 2 - Session structure
00:00-00:05 Kickoff: facilitator presents the feature scope; reads ACs aloud
00:05-00:25 Silent brainstorm: each participant lists 5-10 risks (post-its or shared doc)
00:25-00:40 Affinity grouping: cluster risks by category
00:40-00:55 Score each risk: impact (1-5) × likelihood (1-5)
00:55-01:15 Mitigation discussion + owner assignment
01:15-01:30 Review + close: confirm action itemsThe silent-brainstorm phase is critical - without it, the loudest voice dominates and group-think hides real risks.
Step 3 - Prompts per category
The facilitator brings prompts to drive the brainstorm, one set per risk category (categories align with SKILL.md Step 3). The prompts are starters; the participants extend per the feature.
Business risks
Technical risks
Regulatory / compliance risks
UX risks
Security risks
Performance risks
Step 4 - Affinity grouping
After the silent brainstorm, cluster:
Cluster: "Payment failures"
- Stripe webhook delivery failure
- Stripe API rate limit
- Customer card declined mid-checkout
- Customer cancels mid-checkout (browser back button)
Cluster: "Promo math"
- Off-by-cent rounding
- Stack two promos
- Apply expired promo
- Apply promo to free-shipping order
Cluster: "EU compliance"
- VAT calculation
- GDPR data export
- Cookie consent
Cluster: "..."Clusters reveal that some risks are different facets of one underlying issue (e.g., "payment failures" is one architectural concern; mitigations may apply across the cluster).
Step 5 - Score
Per cluster (or per-row if the cluster has heterogeneous risks):
| Risk | Impact (1-5) | Likelihood (1-5) | Score |
|---|---|---|---|
| Off-by-cent rounding | 5 | 3 | 15 |
| Stack two promos | 4 | 4 | 16 |
| ... (one row per risk) |
The team agrees on each score via brief discussion (5 min cap per risk). When discussion exceeds the cap, the facilitator notes the disagreement and moves on; revisit after the session.
Step 6 - Mitigations + owners
For each Critical (>=15) and High (9-14) risk:
| Risk | Mitigation | Owner | Due |
|---|---|---|---|
| Off-by-cent rounding | Property-based tests on rounding | Alice | 2026-05-15 |
| Stack two promos | Add validation + integration test | Bob | 2026-05-12 |
| Stripe webhook delivery failure | Retry + DLQ + chaos test | Carol | 2026-05-12 |
Lower-priority risks (Medium / Low) get logged but may not get immediate mitigations.
Step 7 - Output to the risk matrix
The session output flows directly into the matrix per SKILL.md Step 2. The matrix file becomes the canonical record; the session notes (silent brainstorm results, discussion points) get attached as appendix.
Step 8 - Post-session
Within 1 day:
A risk-storming session without follow-up is wasted.
Worked example
A team is about to build checkout promo codes. In the kickoff session:
The session ends with a scored, owned Critical risk and a matrix row - not a vague "we should test rounding" note.
Anti-patterns
| Anti-pattern | Why it fails | Fix |
|---|---|---|
| Skipping the silent-brainstorm phase | Loudest voice dominates; quiet engineers' risks invisible. | 20-min silent brainstorm (Step 2). |
| Single-person facilitator + scribe + participant | Facilitator can't focus; participants distracted. | Separate facilitator + note-taker. |
| Open-ended "what could go wrong?" without prompts | Participants stare blankly; brainstorm thin. | Use category prompts (Step 3). |
| Skipping mitigation step | Risks identified; no action. | Mitigation + owner per Critical/High (Step 6). |
| Scoring debates that exceed time cap | Session runs long; later risks get less time. | 5-min cap per risk; flag disagreements (Step 5). |
| Single-team session | Misses cross-team risks (security, compliance, infrastructure). | Invite across functions (Step 1). |
| Risks logged but not in the matrix | Lost; same risks re-discovered next quarter. | Update the matrix (Step 7). |
| No post-session follow-up | Mitigations don't ship; team distrusts the process. | Sprint check-in (Step 8). |
Limitations
References
Related skills
attack-surface-test-checklist
Maps a code change to the security tests worth running against it. Classifies changed paths and file contents into nine attack surfaces (authentication, session management, input handling, file upload, deserialization, access control, API and web service, cryptography, data protection), attaches the matching OWASP ASVS 4.0.3 verification requirements, OWASP Top 10 2021 category IDs, and OWASP WSTG section numbers to each active surface, then emits a per-surface manual and automated test checklist bounded by what actually changed. Surfaces with no changed lines are excluded rather than carried as filler. Use when a pull request, release branch, or feature is about to be security tested and the team needs a targeted test list instead of a generic application-wide checklist.
definition-of-done
The team's Definition of Done (DoD), both halves of the lifecycle: authoring and auditing. Explains the Scrum Guide's DoD definition ("a formal description of the state of the Increment when it meets the quality measures required for the product"), proposes a starter DoD with the 7-10 lines most teams need (code reviewed, unit tests, docs, AC met, deployed to staging, smoke passed, no a11y regressions, telemetry wired), emits a per-PR checklist a reviewer enforces, and audits work against an existing DoD line by line with repository evidence (review records, diffs, CI runs, coverage reports), tagging every line met, not met, or unverifiable - never passing a line on self-attestation. Use when the team doesn't have a DoD, wants to revise theirs, or is about to mark a story or PR done and nobody has checked the work against the committed checklist.
e2e-suite-budget
Caps E2E suite size by computing per-test ROI - (regressions caught × value) ÷ (runtime × flake rate × maintenance) - then ranks every end-to-end test and recommends which bottom-decile ones to retire, move to a lower layer, or fix. Use when CI is slow or E2E-dominated, flaky failures are rising, or quarterly to keep suite size within maintenance capacity. For strategic unit:service:UI layer ratios use test-pyramid-balancer, for the minimal per-deploy critical-path gate use smoke-suite-gate, and for quarantining flaky tests use flaky-test-quarantine; this prunes low-signal tests by ROI.
framework-choice-advisor
Reference catalog for picking a test automation framework or QA tool - covers Playwright / Cypress / Selenium / WebdriverIO / Appium / Espresso / XCUITest / RestAssured / Karate / k6 / Locust with side-by-side tradeoffs on speed, cross-browser, mobile, parallelisation, language support, ecosystem maturity, CI integration; a decision tree matching project NFRs to framework choice; and reference layouts for the chosen stack. references/ extends the same decision to commercial procurement (seven-axis vendor evaluation for TCM platforms, no-code tools, visual-regression services) and to recording the outcome (ADR-based tool-selection decision record with signal, one recommendation, flip conditions). This is the upstream selection step: it decides which tool to adopt, not how to configure one already chosen. Use when starting a new test-automation suite, evaluating commercial QA vendors, or writing down a tool decision.
post-mortem-author
Build-an-X workflow that produces a blameless post-mortem from an incident - captures the timeline (chronological event sequence with sources), root cause analysis (what + why, not who), impact (users / revenue / SLO debt), action items (with owners + due dates + measurable success criteria), and "what went well" (intentional). Per Google SRE: "Blameless postmortems are a tenet of SRE culture." Use after every user-visible incident, not just severe ones.
smoke-suite-gate
Build-an-X workflow for a critical-path smoke suite that runs in <5 minutes - picks the 5-15 highest-business-value journeys (login, hero flow, checkout, payment, primary read), implements as fast E2E or API tests, gates per-deploy, retries on transient failures with quarantine. Use as the canary-precursor or per-deploy verification gate; the team's "if this fails, the build can't proceed" floor.
test-case-from-live-feature
Build-an-X workflow that produces a test-case matrix from a **live, undocumented feature** - running app at a URL, screen recording, screenshot, or verbal brief - by combining structured exploration (Playwright trace / DevTools / accessibility tree) with the four canonical heuristic test-design models bundled in references/ (Bach's HTSM / SFDPOT product elements, Whittaker's How-to-Break-Software attacks, Bolton's FEW HICCUPPS consistency oracles, ISO/IEC 25010 quality characteristics). Output is a structured case matrix, not an exploratory session charter. Use when there is no story, no AC, and no documentation - only a live feature - or as the heuristic reference layer for zero-documentation test design.
test-case-ideation-from-story
Turns a thin or ambiguous story into a reviewable test list - a backlog item that is a short paragraph plus the click-through support recorded for themselves, a spec that is mostly a list of accepted formats, or a tech design pasted into the ticket while the last few releases still shipped missed cases. Takes the story or feature spec and emits a markdown test-case matrix, one row per case (id, title, precondition, steps, expected, tier), covering happy path, alternate paths, boundaries, and negative paths, before any test code is written. Output is the human-reviewable matrix that goes into TestRail / Qase / Xray, not Gherkin scenarios. Use when a story needs its cases enumerated and agreed before automation starts.
test-effort-estimation
Turns a list of testable areas plus a change-shape distribution into a PERT three-point test effort estimate, reporting every row as a range around the expected value rather than a single number, requiring a named assumptions ledger across six mandatory categories, and recommending a per-layer ownership split across developer, automation, and exploratory roles. Bundles the change-shape classifier (pure-logic / service-layer / ui-heavy / data-heavy from git-history path and content signals, with the relative per-layer cost model) as a reference, so the shape distribution the estimate consumes can be produced here too. Does not choose which tests to run or how deep coverage should go. Use when an epic or release has been broken into testable areas and someone is about to commit test capacity for a sprint, or when a change set needs its shape classified before planning.
test-pyramid-balancer
Build-an-X workflow that analyzes a repo's test mix (unit / integration / E2E counts + runtimes) and recommends rebalancing toward the test pyramid ratios per the change-set shape - pure-logic-heavy repo wants ~80/15/5; UI-heavy repo wants ~60/25/15. Detects 'ice-cream cone' (E2E-heavy) and 'hourglass' (integration-thin) anti-patterns. Use when the user asks about test distribution, test strategy, test balance, too many E2E tests, slow CI caused by tests, testing best practices, or rebalancing their test suite; also suitable for quarterly calibration of the test mix to codebase reality.
test-strategy-author
Authors a test strategy document (a master test plan) for a project, release, or feature - covers scope, in/out, test types per layer (unit / integration / contract / E2E / perf / security / a11y), risk-based test prioritization that maps top risks to test investment (per `risk-matrix`), tooling stack, environments, exit criteria, and ownership. Includes a risk-based test-planning workflow that turns a feature scope plus the risk matrix into a budgeted per-risk test plan with owners, effort estimates, and an explicit risks-not-addressed section. Use when a team needs the release-readiness artifact stakeholders sign off on before significant test investment, or a risk-prioritized test plan for a feature or quarter.