602 lines
19 KiB
Markdown
602 lines
19 KiB
Markdown
# Probability and Impact Scale
|
||
|
||
## Principle
|
||
|
||
Risk scoring uses a **probability × impact** matrix (1-9 scale) to prioritize testing efforts. Higher scores (6-9) demand immediate action; lower scores (1-3) require documentation only. This systematic approach ensures testing resources focus on the highest-value risks.
|
||
|
||
## Rationale
|
||
|
||
**The Problem**: Without quantifiable risk assessment, teams over-test low-value scenarios while missing critical risks. Gut feeling leads to inconsistent prioritization and missed edge cases.
|
||
|
||
**The Solution**: Standardize risk evaluation with a 3×3 matrix (probability: 1-3, impact: 1-3). Multiply to derive risk score (1-9). Automate classification (DOCUMENT, MONITOR, MITIGATE, BLOCK) based on thresholds. This approach surfaces hidden risks early and justifies testing decisions to stakeholders.
|
||
|
||
**Why This Matters**:
|
||
|
||
- Consistent risk language across product, engineering, and QA
|
||
- Objective prioritization of test scenarios (not politics)
|
||
- Automatic gate decisions (score=9 → FAIL until resolved)
|
||
- Audit trail for compliance and retrospectives
|
||
|
||
## Pattern Examples
|
||
|
||
### Example 1: Probability-Impact Matrix Implementation (Automated Classification)
|
||
|
||
**Context**: Implement a reusable risk scoring system with automatic threshold classification
|
||
|
||
**Implementation**:
|
||
|
||
```typescript
|
||
// src/testing/risk-matrix.ts
|
||
|
||
/**
|
||
* Probability levels:
|
||
* 1 = Unlikely (standard implementation, low uncertainty)
|
||
* 2 = Possible (edge cases or partial unknowns)
|
||
* 3 = Likely (known issues, new integrations, high ambiguity)
|
||
*/
|
||
export type Probability = 1 | 2 | 3;
|
||
|
||
/**
|
||
* Impact levels:
|
||
* 1 = Minor (cosmetic issues or easy workarounds)
|
||
* 2 = Degraded (partial feature loss or manual workaround)
|
||
* 3 = Critical (blockers, data/security/regulatory exposure)
|
||
*/
|
||
export type Impact = 1 | 2 | 3;
|
||
|
||
/**
|
||
* Risk score (probability × impact): 1-9
|
||
*/
|
||
export type RiskScore = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
|
||
|
||
/**
|
||
* Action categories based on risk score thresholds
|
||
*/
|
||
export type RiskAction = 'DOCUMENT' | 'MONITOR' | 'MITIGATE' | 'BLOCK';
|
||
|
||
export type RiskAssessment = {
|
||
probability: Probability;
|
||
impact: Impact;
|
||
score: RiskScore;
|
||
action: RiskAction;
|
||
reasoning: string;
|
||
};
|
||
|
||
/**
|
||
* Calculate risk score: probability × impact
|
||
*/
|
||
export function calculateRiskScore(probability: Probability, impact: Impact): RiskScore {
|
||
return (probability * impact) as RiskScore;
|
||
}
|
||
|
||
/**
|
||
* Classify risk action based on score thresholds:
|
||
* - 1-3: DOCUMENT (awareness only)
|
||
* - 4-5: MONITOR (watch closely, plan mitigations)
|
||
* - 6-8: MITIGATE (CONCERNS at gate until mitigated)
|
||
* - 9: BLOCK (automatic FAIL until resolved or waived)
|
||
*/
|
||
export function classifyRiskAction(score: RiskScore): RiskAction {
|
||
if (score >= 9) return 'BLOCK';
|
||
if (score >= 6) return 'MITIGATE';
|
||
if (score >= 4) return 'MONITOR';
|
||
return 'DOCUMENT';
|
||
}
|
||
|
||
/**
|
||
* Full risk assessment with automatic classification
|
||
*/
|
||
export function assessRisk(params: { probability: Probability; impact: Impact; reasoning: string }): RiskAssessment {
|
||
const { probability, impact, reasoning } = params;
|
||
|
||
const score = calculateRiskScore(probability, impact);
|
||
const action = classifyRiskAction(score);
|
||
|
||
return { probability, impact, score, action, reasoning };
|
||
}
|
||
|
||
/**
|
||
* Generate risk matrix visualization (3x3 grid)
|
||
* Returns markdown table with color-coded scores
|
||
*/
|
||
export function generateRiskMatrix(): string {
|
||
const matrix: string[][] = [];
|
||
const header = ['Impact \\ Probability', 'Unlikely (1)', 'Possible (2)', 'Likely (3)'];
|
||
matrix.push(header);
|
||
|
||
const impactLabels = ['Critical (3)', 'Degraded (2)', 'Minor (1)'];
|
||
for (let impact = 3; impact >= 1; impact--) {
|
||
const row = [impactLabels[3 - impact]];
|
||
for (let probability = 1; probability <= 3; probability++) {
|
||
const score = calculateRiskScore(probability as Probability, impact as Impact);
|
||
const action = classifyRiskAction(score);
|
||
const emoji = action === 'BLOCK' ? '🔴' : action === 'MITIGATE' ? '🟠' : action === 'MONITOR' ? '🟡' : '🟢';
|
||
row.push(`${emoji} ${score}`);
|
||
}
|
||
matrix.push(row);
|
||
}
|
||
|
||
return matrix.map((row) => `| ${row.join(' | ')} |`).join('\n');
|
||
}
|
||
```
|
||
|
||
**Key Points**:
|
||
|
||
- Type-safe probability/impact (1-3 enforced at compile time)
|
||
- Automatic action classification (DOCUMENT, MONITOR, MITIGATE, BLOCK)
|
||
- Visual matrix generation for documentation
|
||
- Risk score formula: `probability * impact` (max = 9)
|
||
- Threshold-based decision rules (6-8 = MITIGATE, 9 = BLOCK)
|
||
|
||
---
|
||
|
||
### Example 2: Risk Assessment Workflow (Test Planning Integration)
|
||
|
||
**Context**: Apply risk matrix during test design to prioritize scenarios
|
||
|
||
**Implementation**:
|
||
|
||
```typescript
|
||
// tests/e2e/test-planning/risk-assessment.ts
|
||
import { assessRisk, generateRiskMatrix, type RiskAssessment } from '../../../src/testing/risk-matrix';
|
||
|
||
export type TestScenario = {
|
||
id: string;
|
||
title: string;
|
||
feature: string;
|
||
risk: RiskAssessment;
|
||
testLevel: 'E2E' | 'API' | 'Unit';
|
||
priority: 'P0' | 'P1' | 'P2' | 'P3';
|
||
owner: string;
|
||
};
|
||
|
||
/**
|
||
* Assess test scenarios and auto-assign priority based on risk score
|
||
*/
|
||
export function assessTestScenarios(scenarios: Omit<TestScenario, 'risk' | 'priority'>[]): TestScenario[] {
|
||
return scenarios.map((scenario) => {
|
||
// Auto-assign priority based on risk score
|
||
const priority = mapRiskToPriority(scenario.risk.score);
|
||
return { ...scenario, priority };
|
||
});
|
||
}
|
||
|
||
/**
|
||
* Map risk score to test priority (P0-P3)
|
||
* P0: Critical (score 9) - blocks release
|
||
* P1: High (score 6-8) - must fix before release
|
||
* P2: Medium (score 4-5) - fix if time permits
|
||
* P3: Low (score 1-3) - document and defer
|
||
*/
|
||
function mapRiskToPriority(score: number): 'P0' | 'P1' | 'P2' | 'P3' {
|
||
if (score === 9) return 'P0';
|
||
if (score >= 6) return 'P1';
|
||
if (score >= 4) return 'P2';
|
||
return 'P3';
|
||
}
|
||
|
||
/**
|
||
* Example: Payment flow risk assessment
|
||
*/
|
||
export const paymentScenarios: Array<Omit<TestScenario, 'priority'>> = [
|
||
{
|
||
id: 'PAY-001',
|
||
title: 'Valid credit card payment completes successfully',
|
||
feature: 'Checkout',
|
||
risk: assessRisk({
|
||
probability: 2, // Possible (standard Stripe integration)
|
||
impact: 3, // Critical (revenue loss if broken)
|
||
reasoning: 'Core revenue flow, but Stripe is well-tested',
|
||
}),
|
||
testLevel: 'E2E',
|
||
owner: 'qa-team',
|
||
},
|
||
{
|
||
id: 'PAY-002',
|
||
title: 'Expired credit card shows user-friendly error',
|
||
feature: 'Checkout',
|
||
risk: assessRisk({
|
||
probability: 3, // Likely (edge case handling often buggy)
|
||
impact: 2, // Degraded (users see error, but can retry)
|
||
reasoning: 'Error handling logic is custom and complex',
|
||
}),
|
||
testLevel: 'E2E',
|
||
owner: 'qa-team',
|
||
},
|
||
{
|
||
id: 'PAY-003',
|
||
title: 'Payment confirmation email formatting is correct',
|
||
feature: 'Email',
|
||
risk: assessRisk({
|
||
probability: 2, // Possible (template changes occasionally break)
|
||
impact: 1, // Minor (cosmetic issue, email still sent)
|
||
reasoning: 'Non-blocking, users get email regardless',
|
||
}),
|
||
testLevel: 'Unit',
|
||
owner: 'dev-team',
|
||
},
|
||
{
|
||
id: 'PAY-004',
|
||
title: 'Payment fails gracefully when Stripe is down',
|
||
feature: 'Checkout',
|
||
risk: assessRisk({
|
||
probability: 1, // Unlikely (Stripe has 99.99% uptime)
|
||
impact: 3, // Critical (complete checkout failure)
|
||
reasoning: 'Rare but catastrophic, requires retry mechanism',
|
||
}),
|
||
testLevel: 'API',
|
||
owner: 'qa-team',
|
||
},
|
||
];
|
||
|
||
/**
|
||
* Generate risk assessment report with priority distribution
|
||
*/
|
||
export function generateRiskReport(scenarios: TestScenario[]): string {
|
||
const priorityCounts = scenarios.reduce(
|
||
(acc, s) => {
|
||
acc[s.priority] = (acc[s.priority] || 0) + 1;
|
||
return acc;
|
||
},
|
||
{} as Record<string, number>,
|
||
);
|
||
|
||
const actionCounts = scenarios.reduce(
|
||
(acc, s) => {
|
||
acc[s.risk.action] = (acc[s.risk.action] || 0) + 1;
|
||
return acc;
|
||
},
|
||
{} as Record<string, number>,
|
||
);
|
||
|
||
return `
|
||
# Risk Assessment Report
|
||
|
||
## Risk Matrix
|
||
${generateRiskMatrix()}
|
||
|
||
## Priority Distribution
|
||
- **P0 (Blocker)**: ${priorityCounts.P0 || 0} scenarios
|
||
- **P1 (High)**: ${priorityCounts.P1 || 0} scenarios
|
||
- **P2 (Medium)**: ${priorityCounts.P2 || 0} scenarios
|
||
- **P3 (Low)**: ${priorityCounts.P3 || 0} scenarios
|
||
|
||
## Action Required
|
||
- **BLOCK**: ${actionCounts.BLOCK || 0} scenarios (auto-fail gate)
|
||
- **MITIGATE**: ${actionCounts.MITIGATE || 0} scenarios (concerns at gate)
|
||
- **MONITOR**: ${actionCounts.MONITOR || 0} scenarios (watch closely)
|
||
- **DOCUMENT**: ${actionCounts.DOCUMENT || 0} scenarios (awareness only)
|
||
|
||
## Scenarios by Risk Score (Highest First)
|
||
${scenarios
|
||
.sort((a, b) => b.risk.score - a.risk.score)
|
||
.map((s) => `- **[${s.priority}]** ${s.id}: ${s.title} (Score: ${s.risk.score} - ${s.risk.action})`)
|
||
.join('\n')}
|
||
`.trim();
|
||
}
|
||
```
|
||
|
||
**Key Points**:
|
||
|
||
- Risk score → Priority mapping (P0-P3 automated)
|
||
- Report generation with priority/action distribution
|
||
- Scenarios sorted by risk score (highest first)
|
||
- Visual matrix included in reports
|
||
- Reusable across projects (extract to shared library)
|
||
|
||
---
|
||
|
||
### Example 3: Dynamic Risk Re-Assessment (Continuous Evaluation)
|
||
|
||
**Context**: Recalculate risk scores as project evolves (requirements change, mitigations implemented)
|
||
|
||
**Implementation**:
|
||
|
||
```typescript
|
||
// src/testing/risk-tracking.ts
|
||
import { type RiskAssessment, assessRisk, type Probability, type Impact } from './risk-matrix';
|
||
|
||
export type RiskHistory = {
|
||
timestamp: Date;
|
||
assessment: RiskAssessment;
|
||
changedBy: string;
|
||
reason: string;
|
||
};
|
||
|
||
export type TrackedRisk = {
|
||
id: string;
|
||
title: string;
|
||
feature: string;
|
||
currentRisk: RiskAssessment;
|
||
history: RiskHistory[];
|
||
mitigations: string[];
|
||
status: 'OPEN' | 'MITIGATED' | 'WAIVED' | 'RESOLVED';
|
||
};
|
||
|
||
export class RiskTracker {
|
||
private risks: Map<string, TrackedRisk> = new Map();
|
||
|
||
/**
|
||
* Add new risk to tracker
|
||
*/
|
||
addRisk(params: {
|
||
id: string;
|
||
title: string;
|
||
feature: string;
|
||
probability: Probability;
|
||
impact: Impact;
|
||
reasoning: string;
|
||
changedBy: string;
|
||
}): TrackedRisk {
|
||
const { id, title, feature, probability, impact, reasoning, changedBy } = params;
|
||
|
||
const assessment = assessRisk({ probability, impact, reasoning });
|
||
|
||
const risk: TrackedRisk = {
|
||
id,
|
||
title,
|
||
feature,
|
||
currentRisk: assessment,
|
||
history: [
|
||
{
|
||
timestamp: new Date(),
|
||
assessment,
|
||
changedBy,
|
||
reason: 'Initial assessment',
|
||
},
|
||
],
|
||
mitigations: [],
|
||
status: 'OPEN',
|
||
};
|
||
|
||
this.risks.set(id, risk);
|
||
return risk;
|
||
}
|
||
|
||
/**
|
||
* Reassess risk (probability or impact changed)
|
||
*/
|
||
reassessRisk(params: {
|
||
id: string;
|
||
probability?: Probability;
|
||
impact?: Impact;
|
||
reasoning: string;
|
||
changedBy: string;
|
||
}): TrackedRisk | null {
|
||
const { id, probability, impact, reasoning, changedBy } = params;
|
||
const risk = this.risks.get(id);
|
||
if (!risk) return null;
|
||
|
||
// Use existing values if not provided
|
||
const newProbability = probability ?? risk.currentRisk.probability;
|
||
const newImpact = impact ?? risk.currentRisk.impact;
|
||
|
||
const newAssessment = assessRisk({
|
||
probability: newProbability,
|
||
impact: newImpact,
|
||
reasoning,
|
||
});
|
||
|
||
risk.currentRisk = newAssessment;
|
||
risk.history.push({
|
||
timestamp: new Date(),
|
||
assessment: newAssessment,
|
||
changedBy,
|
||
reason: reasoning,
|
||
});
|
||
|
||
this.risks.set(id, risk);
|
||
return risk;
|
||
}
|
||
|
||
/**
|
||
* Mark risk as mitigated (probability reduced)
|
||
*/
|
||
mitigateRisk(params: { id: string; newProbability: Probability; mitigation: string; changedBy: string }): TrackedRisk | null {
|
||
const { id, newProbability, mitigation, changedBy } = params;
|
||
const risk = this.reassessRisk({
|
||
id,
|
||
probability: newProbability,
|
||
reasoning: `Mitigation implemented: ${mitigation}`,
|
||
changedBy,
|
||
});
|
||
|
||
if (risk) {
|
||
risk.mitigations.push(mitigation);
|
||
if (risk.currentRisk.action === 'DOCUMENT' || risk.currentRisk.action === 'MONITOR') {
|
||
risk.status = 'MITIGATED';
|
||
}
|
||
}
|
||
|
||
return risk;
|
||
}
|
||
|
||
/**
|
||
* Get risks requiring action (MITIGATE or BLOCK)
|
||
*/
|
||
getRisksRequiringAction(): TrackedRisk[] {
|
||
return Array.from(this.risks.values()).filter(
|
||
(r) => r.status === 'OPEN' && (r.currentRisk.action === 'MITIGATE' || r.currentRisk.action === 'BLOCK'),
|
||
);
|
||
}
|
||
|
||
/**
|
||
* Generate risk trend report (show changes over time)
|
||
*/
|
||
generateTrendReport(riskId: string): string | null {
|
||
const risk = this.risks.get(riskId);
|
||
if (!risk) return null;
|
||
|
||
return `
|
||
# Risk Trend Report: ${risk.id}
|
||
|
||
**Title**: ${risk.title}
|
||
**Feature**: ${risk.feature}
|
||
**Status**: ${risk.status}
|
||
|
||
## Current Assessment
|
||
- **Probability**: ${risk.currentRisk.probability}
|
||
- **Impact**: ${risk.currentRisk.impact}
|
||
- **Score**: ${risk.currentRisk.score}
|
||
- **Action**: ${risk.currentRisk.action}
|
||
- **Reasoning**: ${risk.currentRisk.reasoning}
|
||
|
||
## Mitigations Applied
|
||
${risk.mitigations.length > 0 ? risk.mitigations.map((m) => `- ${m}`).join('\n') : '- None'}
|
||
|
||
## History (${risk.history.length} changes)
|
||
${risk.history
|
||
.reverse()
|
||
.map((h) => `- **${h.timestamp.toISOString()}** by ${h.changedBy}: Score ${h.assessment.score} (${h.assessment.action}) - ${h.reason}`)
|
||
.join('\n')}
|
||
`.trim();
|
||
}
|
||
}
|
||
```
|
||
|
||
**Key Points**:
|
||
|
||
- Historical tracking (audit trail for risk changes)
|
||
- Mitigation impact tracking (probability reduction)
|
||
- Status lifecycle (OPEN → MITIGATED → RESOLVED)
|
||
- Trend reports (show risk evolution over time)
|
||
- Re-assessment triggers (requirements change, new info)
|
||
|
||
---
|
||
|
||
### Example 4: Risk Matrix in Gate Decision (Integration with Trace Workflow)
|
||
|
||
**Context**: Use probability-impact scores to drive gate decisions (PASS/CONCERNS/FAIL/WAIVED)
|
||
|
||
**Implementation**:
|
||
|
||
```typescript
|
||
// src/testing/gate-decision.ts
|
||
import { type RiskScore, classifyRiskAction, type RiskAction } from './risk-matrix';
|
||
import { type TrackedRisk } from './risk-tracking';
|
||
|
||
export type GateDecision = 'PASS' | 'CONCERNS' | 'FAIL' | 'WAIVED';
|
||
|
||
export type GateResult = {
|
||
decision: GateDecision;
|
||
blockers: TrackedRisk[]; // Score=9, action=BLOCK
|
||
concerns: TrackedRisk[]; // Score 6-8, action=MITIGATE
|
||
monitored: TrackedRisk[]; // Score 4-5, action=MONITOR
|
||
documented: TrackedRisk[]; // Score 1-3, action=DOCUMENT
|
||
summary: string;
|
||
};
|
||
|
||
/**
|
||
* Evaluate gate based on risk assessments
|
||
*/
|
||
export function evaluateGateFromRisks(risks: TrackedRisk[]): GateResult {
|
||
const blockers = risks.filter((r) => r.currentRisk.action === 'BLOCK' && r.status === 'OPEN');
|
||
const concerns = risks.filter((r) => r.currentRisk.action === 'MITIGATE' && r.status === 'OPEN');
|
||
const monitored = risks.filter((r) => r.currentRisk.action === 'MONITOR');
|
||
const documented = risks.filter((r) => r.currentRisk.action === 'DOCUMENT');
|
||
|
||
let decision: GateDecision;
|
||
|
||
if (blockers.length > 0) {
|
||
decision = 'FAIL';
|
||
} else if (concerns.length > 0) {
|
||
decision = 'CONCERNS';
|
||
} else {
|
||
decision = 'PASS';
|
||
}
|
||
|
||
const summary = generateGateSummary({ decision, blockers, concerns, monitored, documented });
|
||
|
||
return { decision, blockers, concerns, monitored, documented, summary };
|
||
}
|
||
|
||
/**
|
||
* Generate gate decision summary
|
||
*/
|
||
function generateGateSummary(result: Omit<GateResult, 'summary'>): string {
|
||
const { decision, blockers, concerns, monitored, documented } = result;
|
||
|
||
const lines: string[] = [`## Gate Decision: ${decision}`];
|
||
|
||
if (decision === 'FAIL') {
|
||
lines.push(`\n**Blockers** (${blockers.length}): Automatic FAIL until resolved or waived`);
|
||
blockers.forEach((r) => {
|
||
lines.push(`- **${r.id}**: ${r.title} (Score: ${r.currentRisk.score})`);
|
||
lines.push(` - Probability: ${r.currentRisk.probability}, Impact: ${r.currentRisk.impact}`);
|
||
lines.push(` - Reasoning: ${r.currentRisk.reasoning}`);
|
||
});
|
||
}
|
||
|
||
if (concerns.length > 0) {
|
||
lines.push(`\n**Concerns** (${concerns.length}): Address before release`);
|
||
concerns.forEach((r) => {
|
||
lines.push(`- **${r.id}**: ${r.title} (Score: ${r.currentRisk.score})`);
|
||
lines.push(` - Mitigations: ${r.mitigations.join(', ') || 'None'}`);
|
||
});
|
||
}
|
||
|
||
if (monitored.length > 0) {
|
||
lines.push(`\n**Monitored** (${monitored.length}): Watch closely`);
|
||
monitored.forEach((r) => lines.push(`- **${r.id}**: ${r.title} (Score: ${r.currentRisk.score})`));
|
||
}
|
||
|
||
if (documented.length > 0) {
|
||
lines.push(`\n**Documented** (${documented.length}): Awareness only`);
|
||
}
|
||
|
||
lines.push(`\n---\n`);
|
||
lines.push(`**Next Steps**:`);
|
||
if (decision === 'FAIL') {
|
||
lines.push(`- Resolve blockers or request formal waiver`);
|
||
} else if (decision === 'CONCERNS') {
|
||
lines.push(`- Implement mitigations for high-risk scenarios (score 6-8)`);
|
||
lines.push(`- Re-run gate after mitigations`);
|
||
} else {
|
||
lines.push(`- Proceed with release`);
|
||
}
|
||
|
||
return lines.join('\n');
|
||
}
|
||
```
|
||
|
||
**Key Points**:
|
||
|
||
- Gate decision driven by risk scores (not gut feeling)
|
||
- Automatic FAIL for score=9 (blockers)
|
||
- CONCERNS for score 6-8 (requires mitigation)
|
||
- PASS only when no blockers/concerns
|
||
- Actionable summary with next steps
|
||
- Integration with trace workflow (Phase 2)
|
||
|
||
---
|
||
|
||
## Probability-Impact Threshold Summary
|
||
|
||
| Score | Action | Gate Impact | Typical Use Case |
|
||
| ----- | -------- | -------------------- | -------------------------------------- |
|
||
| 1-3 | DOCUMENT | None | Cosmetic issues, low-priority bugs |
|
||
| 4-5 | MONITOR | None (watch closely) | Edge cases, partial unknowns |
|
||
| 6-8 | MITIGATE | CONCERNS at gate | High-impact scenarios needing coverage |
|
||
| 9 | BLOCK | Automatic FAIL | Critical blockers, must resolve |
|
||
|
||
## Risk Assessment Checklist
|
||
|
||
Before deploying risk matrix:
|
||
|
||
- [ ] **Probability scale defined**: 1 (unlikely), 2 (possible), 3 (likely) with clear examples
|
||
- [ ] **Impact scale defined**: 1 (minor), 2 (degraded), 3 (critical) with concrete criteria
|
||
- [ ] **Threshold rules documented**: Score → Action mapping (1-3 = DOCUMENT, 4-5 = MONITOR, 6-8 = MITIGATE, 9 = BLOCK)
|
||
- [ ] **Gate integration**: Risk scores drive gate decisions (PASS/CONCERNS/FAIL/WAIVED)
|
||
- [ ] **Re-assessment process**: Risks re-evaluated as project evolves (requirements change, mitigations applied)
|
||
- [ ] **Audit trail**: Historical tracking for risk changes (who, when, why)
|
||
- [ ] **Mitigation tracking**: Link mitigations to probability reduction (quantify impact)
|
||
- [ ] **Reporting**: Risk matrix visualization, trend reports, gate summaries
|
||
|
||
## Integration Points
|
||
|
||
- **Used in workflows**: `*test-design` (initial risk assessment), `*trace` (gate decision Phase 2), `*nfr-assess` (security/performance risks)
|
||
- **Related fragments**: `risk-governance.md` (risk scoring matrix, gate decision engine), `test-priorities-matrix.md` (P0-P3 mapping), `nfr-criteria.md` (impact assessment for NFRs)
|
||
- **Tools**: TypeScript for type safety, markdown for reports, version control for audit trail
|
||
|
||
_Source: Murat risk model summary, gate decision patterns from production systems, probability-impact matrix from risk governance practices_
|