@odavl/guardian 2.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +210 -210
- package/LICENSE +21 -21
- package/README.md +297 -184
- package/bin/guardian.js +2242 -2221
- package/config/README.md +59 -59
- package/config/guardian.config.json +54 -54
- package/config/guardian.policy.json +12 -12
- package/config/profiles/docs.yaml +18 -18
- package/config/profiles/ecommerce.yaml +17 -17
- package/config/profiles/landing-demo.yaml +16 -16
- package/config/profiles/marketing.yaml +18 -18
- package/config/profiles/saas.yaml +21 -21
- package/flows/example-login-flow.json +36 -36
- package/flows/example-signup-flow.json +44 -44
- package/package.json +124 -116
- package/policies/enterprise.json +12 -12
- package/policies/landing-demo.json +22 -22
- package/policies/saas.json +12 -12
- package/policies/startup.json +12 -12
- package/src/enterprise/audit-logger.js +166 -166
- package/src/enterprise/pdf-exporter.js +267 -267
- package/src/enterprise/rbac-gate.js +142 -142
- package/src/enterprise/rbac.js +239 -239
- package/src/enterprise/site-manager.js +180 -180
- package/src/founder/feedback-system.js +156 -156
- package/src/founder/founder-tracker.js +213 -213
- package/src/founder/usage-signals.js +141 -141
- package/src/guardian/action-hints.js +439 -439
- package/src/guardian/alert-ledger.js +121 -121
- package/src/guardian/artifact-sanitizer.js +56 -56
- package/src/guardian/attempt-engine.js +1069 -1029
- package/src/guardian/attempt-registry.js +267 -267
- package/src/guardian/attempt-relevance.js +106 -106
- package/src/guardian/attempt-reporter.js +513 -507
- package/src/guardian/attempt.js +274 -273
- package/src/guardian/attempts-filter.js +63 -63
- package/src/guardian/auto-attempt-builder.js +283 -283
- package/src/guardian/baseline-registry.js +177 -177
- package/src/guardian/baseline-reporter.js +143 -143
- package/src/guardian/baseline-storage.js +285 -285
- package/src/guardian/baseline.js +535 -534
- package/src/guardian/behavioral-signals.js +261 -261
- package/src/guardian/breakage-intelligence.js +224 -224
- package/src/guardian/browser-pool.js +131 -131
- package/src/guardian/browser.js +119 -119
- package/src/guardian/canonical-truth.js +308 -308
- package/src/guardian/ci-cli.js +121 -121
- package/src/guardian/ci-gate.js +96 -96
- package/src/guardian/ci-mode.js +15 -15
- package/src/guardian/ci-output.js +55 -38
- package/src/guardian/cli-summary.js +102 -102
- package/src/guardian/confidence-signals.js +251 -251
- package/src/guardian/config-loader.js +161 -161
- package/src/guardian/config-validator.js +285 -283
- package/src/guardian/coverage-model.js +239 -239
- package/src/guardian/coverage-packs.js +58 -58
- package/src/guardian/crawler.js +142 -142
- package/src/guardian/data-guardian-detector.js +189 -189
- package/src/guardian/decision-authority.js +746 -725
- package/src/guardian/detection-layers.js +271 -271
- package/src/guardian/determinism.js +146 -146
- package/src/guardian/discovery-engine.js +661 -661
- package/src/guardian/drift-detector.js +100 -100
- package/src/guardian/enhanced-html-reporter.js +522 -522
- package/src/guardian/env-guard.js +128 -127
- package/src/guardian/error-clarity.js +399 -399
- package/src/guardian/export-contract.js +196 -196
- package/src/guardian/fail-safe.js +212 -212
- package/src/guardian/failure-intelligence.js +173 -173
- package/src/guardian/failure-taxonomy.js +169 -169
- package/src/guardian/final-outcome.js +206 -206
- package/src/guardian/first-run-profile.js +89 -89
- package/src/guardian/first-run.js +65 -67
- package/src/guardian/flag-validator.js +111 -111
- package/src/guardian/flow-executor.js +641 -639
- package/src/guardian/flow-registry.js +67 -67
- package/src/guardian/honesty.js +394 -394
- package/src/guardian/html-reporter.js +416 -416
- package/src/guardian/human-intent-resolver.js +296 -296
- package/src/guardian/human-interaction-model.js +351 -351
- package/src/guardian/human-journey-context.js +184 -184
- package/src/guardian/human-navigator.js +544 -544
- package/src/guardian/human-reporter.js +435 -431
- package/src/guardian/index.js +226 -221
- package/src/guardian/init-command.js +143 -143
- package/src/guardian/intent-detector.js +148 -146
- package/src/guardian/journey-definitions.js +132 -132
- package/src/guardian/journey-scan-cli.js +142 -145
- package/src/guardian/journey-scanner.js +583 -583
- package/src/guardian/junit-reporter.js +281 -281
- package/src/guardian/language-detection.js +99 -99
- package/src/guardian/live-alert.js +56 -56
- package/src/guardian/live-baseline-compare.js +146 -146
- package/src/guardian/live-cli.js +95 -95
- package/src/guardian/live-guardian.js +210 -210
- package/src/guardian/live-scheduler-runner.js +137 -137
- package/src/guardian/live-scheduler-state.js +167 -168
- package/src/guardian/live-scheduler.js +146 -146
- package/src/guardian/live-state.js +110 -110
- package/src/guardian/market-criticality.js +335 -335
- package/src/guardian/market-reporter.js +577 -577
- package/src/guardian/network-trace.js +178 -178
- package/src/guardian/obs-logger.js +110 -110
- package/src/guardian/observed-capabilities.js +427 -427
- package/src/guardian/output-contract.js +154 -0
- package/src/guardian/output-readability.js +264 -264
- package/src/guardian/parallel-executor.js +116 -116
- package/src/guardian/path-safety.js +56 -56
- package/src/guardian/pattern-analyzer.js +348 -348
- package/src/guardian/policy.js +432 -434
- package/src/guardian/prelaunch-gate.js +193 -193
- package/src/guardian/prerequisite-checker.js +101 -101
- package/src/guardian/preset-loader.js +152 -157
- package/src/guardian/profile-loader.js +96 -96
- package/src/guardian/reality.js +3025 -2826
- package/src/guardian/realworld-scenarios.js +94 -94
- package/src/guardian/reporter.js +167 -167
- package/src/guardian/retry-policy.js +123 -123
- package/src/guardian/root-cause-analysis.js +171 -171
- package/src/guardian/rules-engine.js +558 -558
- package/src/guardian/run-artifacts.js +212 -212
- package/src/guardian/run-cleanup.js +207 -207
- package/src/guardian/run-export.js +522 -522
- package/src/guardian/run-latest.js +90 -90
- package/src/guardian/run-list.js +211 -211
- package/src/guardian/run-summary.js +20 -20
- package/src/guardian/runtime-root.js +246 -246
- package/src/guardian/safety.js +248 -248
- package/src/guardian/scan-presets.js +133 -149
- package/src/guardian/screenshot.js +152 -152
- package/src/guardian/secret-hygiene.js +44 -44
- package/src/guardian/selector-fallbacks.js +394 -394
- package/src/guardian/semantic-contact-detection.js +255 -255
- package/src/guardian/semantic-contact-finder.js +201 -201
- package/src/guardian/semantic-targets.js +234 -234
- package/src/guardian/site-intelligence.js +588 -588
- package/src/guardian/site-introspection.js +257 -257
- package/src/guardian/sitemap.js +225 -225
- package/src/guardian/smoke.js +283 -258
- package/src/guardian/snapshot-schema.js +177 -290
- package/src/guardian/snapshot.js +430 -397
- package/src/guardian/stability-scorer.js +169 -169
- package/src/guardian/success-evaluator.js +214 -214
- package/src/guardian/template-command.js +184 -184
- package/src/guardian/text-formatters.js +426 -426
- package/src/guardian/timeout-profiles.js +57 -57
- package/src/guardian/truth/attempt.contract.js +158 -0
- package/src/guardian/truth/decision.contract.js +275 -0
- package/src/guardian/truth/snapshot.contract.js +363 -0
- package/src/guardian/validators.js +323 -323
- package/src/guardian/verdict-card.js +474 -474
- package/src/guardian/verdict-clarity.js +298 -298
- package/src/guardian/verdict-policy.js +363 -363
- package/src/guardian/verdict.js +333 -333
- package/src/guardian/verdicts.js +79 -74
- package/src/guardian/visual-diff.js +247 -247
- package/src/guardian/wait-for-outcome.js +119 -119
- package/src/guardian/watch-runner.js +181 -181
- package/src/guardian/watchdog-diff.js +167 -167
- package/src/guardian/webhook.js +206 -206
- package/src/payments/stripe-checkout.js +169 -169
- package/src/plans/plan-definitions.js +148 -148
- package/src/plans/plan-manager.js +211 -211
- package/src/plans/usage-tracker.js +210 -210
- package/src/recipes/recipe-engine.js +188 -188
- package/src/recipes/recipe-failure-analysis.js +159 -159
- package/src/recipes/recipe-registry.js +134 -134
- package/src/recipes/recipe-runtime.js +507 -507
- package/src/recipes/recipe-store.js +410 -410
- package/SECURITY.md +0 -77
- package/VERSIONING.md +0 -100
- package/guardian-contract-v1.md +0 -502
|
@@ -1,224 +1,224 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Phase 4 — Breakage Intelligence
|
|
3
|
-
* Aggregate failure taxonomy and hints into actionable summaries
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
const {
|
|
7
|
-
BREAK_TYPES,
|
|
8
|
-
IMPACT_DOMAINS,
|
|
9
|
-
SEVERITY_LEVELS,
|
|
10
|
-
getImpactDomain,
|
|
11
|
-
classifyBreakType,
|
|
12
|
-
determineSeverity
|
|
13
|
-
} = require('./failure-taxonomy');
|
|
14
|
-
const { deriveRootCauseHints } = require('./root-cause-analysis');
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Analyze a single attempt/flow failure and produce intelligence
|
|
18
|
-
* @param {Object} item - Attempt or flow result with outcome, error, validators, visualDiff, behavioralSignals, etc.
|
|
19
|
-
* @param {boolean} isFlow - true if this is a flow
|
|
20
|
-
* @returns {Object} Intelligence object with taxonomy, hints, actions
|
|
21
|
-
*/
|
|
22
|
-
function analyzeFailure(item, isFlow = false) {
|
|
23
|
-
if (!item || item.outcome === 'SUCCESS') {
|
|
24
|
-
return null;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const domain = getImpactDomain(isFlow ? item.flowId : item.attemptId);
|
|
28
|
-
const breakType = classifyBreakType(item);
|
|
29
|
-
const severity = determineSeverity(domain, breakType, isFlow);
|
|
30
|
-
const { hints, primaryHint } = deriveRootCauseHints(item, breakType);
|
|
31
|
-
|
|
32
|
-
// Phase 5: Include visual regression metadata
|
|
33
|
-
const intelligence = {
|
|
34
|
-
id: isFlow ? item.flowId : item.attemptId,
|
|
35
|
-
name: isFlow ? item.flowName : item.attemptName,
|
|
36
|
-
outcome: item.outcome,
|
|
37
|
-
source: isFlow ? 'flow' : 'attempt',
|
|
38
|
-
breakType,
|
|
39
|
-
domain,
|
|
40
|
-
severity,
|
|
41
|
-
primaryHint,
|
|
42
|
-
hints,
|
|
43
|
-
whyItMatters: generateWhyItMatters(domain, severity, breakType),
|
|
44
|
-
topActions: generateTopActions(breakType, domain)
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
// Phase 5: Add visual regression details if available
|
|
48
|
-
if (item.visualDiff) {
|
|
49
|
-
intelligence.visualDiff = {
|
|
50
|
-
hasDiff: item.visualDiff.hasDiff,
|
|
51
|
-
percentChange: item.visualDiff.percentChange,
|
|
52
|
-
reason: item.visualDiff.reason,
|
|
53
|
-
diffRegions: item.visualDiff.diffRegions
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Phase 5: Add behavioral signals if available
|
|
58
|
-
if (item.behavioralSignals) {
|
|
59
|
-
intelligence.behavioralSignals = item.behavioralSignals;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
return intelligence;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Generate 1–3 bullet "Why It Matters" summary
|
|
67
|
-
* @param {string} domain - IMPACT_DOMAIN
|
|
68
|
-
* @param {string} severity - SEVERITY_LEVEL
|
|
69
|
-
* @returns {string[]} Array of 1–3 bullets
|
|
70
|
-
*/
|
|
71
|
-
function generateWhyItMatters(domain, severity, breakType = null) {
|
|
72
|
-
const bullets = [];
|
|
73
|
-
|
|
74
|
-
// Domain-specific impact
|
|
75
|
-
if (domain === IMPACT_DOMAINS.REVENUE) {
|
|
76
|
-
bullets.push('🚨 Revenue impact: Checkout/payment flow is broken. Customers cannot complete purchases.');
|
|
77
|
-
} else if (domain === IMPACT_DOMAINS.LEAD) {
|
|
78
|
-
bullets.push('📉 Lead gen impact: Signup/contact flow is broken. Cannot capture customer interest.');
|
|
79
|
-
} else if (domain === IMPACT_DOMAINS.TRUST) {
|
|
80
|
-
bullets.push('⚠️ Trust impact: Auth/account flow is broken. Users cannot access their data.');
|
|
81
|
-
} else {
|
|
82
|
-
bullets.push('📊 UX impact: Core interaction is broken. User journey degraded.');
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// Severity escalation
|
|
86
|
-
if (severity === SEVERITY_LEVELS.CRITICAL) {
|
|
87
|
-
bullets.push('🔴 CRITICAL: Escalate immediately. Page/API down or core feature broken.');
|
|
88
|
-
} else if (severity === SEVERITY_LEVELS.WARNING) {
|
|
89
|
-
bullets.push('🟡 WARNING: High priority. Fix before peak traffic to avoid customer impact.');
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Phase 5: Visual regression context
|
|
93
|
-
if (breakType === BREAK_TYPES.VISUAL) {
|
|
94
|
-
bullets.push('👁️ Visual regression: UI elements changed from baseline (CSS, layout, or styling).');
|
|
95
|
-
if (severity === SEVERITY_LEVELS.CRITICAL) {
|
|
96
|
-
bullets.push('Critical visual change may completely obscure content or block user interaction.');
|
|
97
|
-
} else if (severity === SEVERITY_LEVELS.WARNING) {
|
|
98
|
-
bullets.push('Visual change may degrade readability, accessibility, or user experience.');
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
return bullets;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Generate top 3 actionable next steps
|
|
107
|
-
* @param {string} breakType - BREAK_TYPE
|
|
108
|
-
* @param {string} domain - IMPACT_DOMAIN
|
|
109
|
-
* @returns {string[]} Array of 3 action strings
|
|
110
|
-
*/
|
|
111
|
-
function generateTopActions(breakType, domain) {
|
|
112
|
-
const actions = [];
|
|
113
|
-
|
|
114
|
-
// Break-type-specific actions
|
|
115
|
-
if (breakType === BREAK_TYPES.NAVIGATION || breakType === BREAK_TYPES.NETWORK) {
|
|
116
|
-
actions.push('1. Check server status and network logs for errors');
|
|
117
|
-
actions.push('2. Verify DNS and SSL certificate validity');
|
|
118
|
-
actions.push('3. Check CDN/load balancer for 5xx errors');
|
|
119
|
-
} else if (breakType === BREAK_TYPES.TIMEOUT) {
|
|
120
|
-
actions.push('1. Check server response times and database queries');
|
|
121
|
-
actions.push('2. Review recent deployments for performance regressions');
|
|
122
|
-
actions.push('3. Check if rate limiting is too strict');
|
|
123
|
-
} else if (breakType === BREAK_TYPES.VISUAL) {
|
|
124
|
-
// Phase 5: Visual-specific diagnostic actions
|
|
125
|
-
actions.push('1. Compare baseline screenshot to current; identify CSS/layout changes');
|
|
126
|
-
actions.push('2. Check recent CSS commits, theme changes, or Tailwind/Bootstrap updates');
|
|
127
|
-
actions.push('3. Validate element positioning using browser DevTools layout analysis');
|
|
128
|
-
} else if (breakType === BREAK_TYPES.VALIDATION) {
|
|
129
|
-
actions.push('1. Review frontend code for recent CSS/JS changes');
|
|
130
|
-
actions.push('2. Check browser console for JavaScript errors');
|
|
131
|
-
actions.push('3. Verify DOM selectors match current HTML structure');
|
|
132
|
-
} else if (breakType === BREAK_TYPES.SUBMISSION) {
|
|
133
|
-
actions.push('1. Check form validation rules and error messages');
|
|
134
|
-
actions.push('2. Verify backend API endpoint is reachable');
|
|
135
|
-
actions.push('3. Check for CORS or authentication failures');
|
|
136
|
-
} else if (breakType === BREAK_TYPES.CONSOLE) {
|
|
137
|
-
actions.push('1. Review browser console error logs');
|
|
138
|
-
actions.push('2. Check for third-party script failures');
|
|
139
|
-
actions.push('3. Verify API endpoints and authentication tokens');
|
|
140
|
-
} else {
|
|
141
|
-
actions.push('1. Check application logs for errors');
|
|
142
|
-
actions.push('2. Verify all dependencies are deployed');
|
|
143
|
-
actions.push('3. Check recent changes that might affect this flow');
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
return actions;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Aggregate all failures into intelligence summary
|
|
151
|
-
* @param {Array} attempts - Attempt results
|
|
152
|
-
* @param {Array} flows - Flow results
|
|
153
|
-
* @returns {Object} Summary with failures, by-domain counts, escalation signals
|
|
154
|
-
*/
|
|
155
|
-
function aggregateIntelligence(attempts = [], flows = []) {
|
|
156
|
-
const allFailures = [];
|
|
157
|
-
const byDomain = {
|
|
158
|
-
[IMPACT_DOMAINS.REVENUE]: [],
|
|
159
|
-
[IMPACT_DOMAINS.LEAD]: [],
|
|
160
|
-
[IMPACT_DOMAINS.TRUST]: [],
|
|
161
|
-
[IMPACT_DOMAINS.UX]: []
|
|
162
|
-
};
|
|
163
|
-
const bySeverity = {
|
|
164
|
-
[SEVERITY_LEVELS.CRITICAL]: [],
|
|
165
|
-
[SEVERITY_LEVELS.WARNING]: [],
|
|
166
|
-
[SEVERITY_LEVELS.INFO]: []
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
// Analyze attempts
|
|
170
|
-
for (const attempt of attempts) {
|
|
171
|
-
const intel = analyzeFailure(attempt, false);
|
|
172
|
-
if (intel) {
|
|
173
|
-
allFailures.push(intel);
|
|
174
|
-
byDomain[intel.domain].push(intel);
|
|
175
|
-
bySeverity[intel.severity].push(intel);
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// Analyze flows (higher weight)
|
|
180
|
-
for (const flow of flows) {
|
|
181
|
-
const intel = analyzeFailure(flow, true);
|
|
182
|
-
if (intel) {
|
|
183
|
-
allFailures.push(intel);
|
|
184
|
-
byDomain[intel.domain].push(intel);
|
|
185
|
-
bySeverity[intel.severity].push(intel);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// Escalation signals
|
|
190
|
-
const escalationSignals = [];
|
|
191
|
-
if (bySeverity[SEVERITY_LEVELS.CRITICAL].length > 0) {
|
|
192
|
-
escalationSignals.push('CRITICAL failures detected - immediate action required');
|
|
193
|
-
}
|
|
194
|
-
if (byDomain[IMPACT_DOMAINS.REVENUE].length > 0) {
|
|
195
|
-
escalationSignals.push('REVENUE domain affected - financial impact likely');
|
|
196
|
-
}
|
|
197
|
-
if (
|
|
198
|
-
flows.filter(f => f.outcome === 'FAILURE').length > 0 ||
|
|
199
|
-
allFailures.filter(f => f.breakType === BREAK_TYPES.NETWORK || f.breakType === BREAK_TYPES.TIMEOUT).length > 0
|
|
200
|
-
) {
|
|
201
|
-
escalationSignals.push('Infrastructure/availability issue indicated');
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
return {
|
|
205
|
-
totalFailures: allFailures.length,
|
|
206
|
-
failures: allFailures,
|
|
207
|
-
byDomain,
|
|
208
|
-
bySeverity,
|
|
209
|
-
escalationSignals,
|
|
210
|
-
criticalCount: bySeverity[SEVERITY_LEVELS.CRITICAL].length,
|
|
211
|
-
warningCount: bySeverity[SEVERITY_LEVELS.WARNING].length,
|
|
212
|
-
infoCount: bySeverity[SEVERITY_LEVELS.INFO].length
|
|
213
|
-
};
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
module.exports = {
|
|
217
|
-
analyzeFailure,
|
|
218
|
-
aggregateIntelligence,
|
|
219
|
-
generateWhyItMatters,
|
|
220
|
-
generateTopActions,
|
|
221
|
-
BREAK_TYPES,
|
|
222
|
-
IMPACT_DOMAINS,
|
|
223
|
-
SEVERITY_LEVELS
|
|
224
|
-
};
|
|
1
|
+
/**
|
|
2
|
+
* Phase 4 — Breakage Intelligence
|
|
3
|
+
* Aggregate failure taxonomy and hints into actionable summaries
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const {
|
|
7
|
+
BREAK_TYPES,
|
|
8
|
+
IMPACT_DOMAINS,
|
|
9
|
+
SEVERITY_LEVELS,
|
|
10
|
+
getImpactDomain,
|
|
11
|
+
classifyBreakType,
|
|
12
|
+
determineSeverity
|
|
13
|
+
} = require('./failure-taxonomy');
|
|
14
|
+
const { deriveRootCauseHints } = require('./root-cause-analysis');
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Analyze a single attempt/flow failure and produce intelligence
|
|
18
|
+
* @param {Object} item - Attempt or flow result with outcome, error, validators, visualDiff, behavioralSignals, etc.
|
|
19
|
+
* @param {boolean} isFlow - true if this is a flow
|
|
20
|
+
* @returns {Object} Intelligence object with taxonomy, hints, actions
|
|
21
|
+
*/
|
|
22
|
+
function analyzeFailure(item, isFlow = false) {
|
|
23
|
+
if (!item || item.outcome === 'SUCCESS') {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const domain = getImpactDomain(isFlow ? item.flowId : item.attemptId);
|
|
28
|
+
const breakType = classifyBreakType(item);
|
|
29
|
+
const severity = determineSeverity(domain, breakType, isFlow);
|
|
30
|
+
const { hints, primaryHint } = deriveRootCauseHints(item, breakType);
|
|
31
|
+
|
|
32
|
+
// Phase 5: Include visual regression metadata
|
|
33
|
+
const intelligence = {
|
|
34
|
+
id: isFlow ? item.flowId : item.attemptId,
|
|
35
|
+
name: isFlow ? item.flowName : item.attemptName,
|
|
36
|
+
outcome: item.outcome,
|
|
37
|
+
source: isFlow ? 'flow' : 'attempt',
|
|
38
|
+
breakType,
|
|
39
|
+
domain,
|
|
40
|
+
severity,
|
|
41
|
+
primaryHint,
|
|
42
|
+
hints,
|
|
43
|
+
whyItMatters: generateWhyItMatters(domain, severity, breakType),
|
|
44
|
+
topActions: generateTopActions(breakType, domain)
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
// Phase 5: Add visual regression details if available
|
|
48
|
+
if (item.visualDiff) {
|
|
49
|
+
intelligence.visualDiff = {
|
|
50
|
+
hasDiff: item.visualDiff.hasDiff,
|
|
51
|
+
percentChange: item.visualDiff.percentChange,
|
|
52
|
+
reason: item.visualDiff.reason,
|
|
53
|
+
diffRegions: item.visualDiff.diffRegions
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Phase 5: Add behavioral signals if available
|
|
58
|
+
if (item.behavioralSignals) {
|
|
59
|
+
intelligence.behavioralSignals = item.behavioralSignals;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return intelligence;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Generate 1–3 bullet "Why It Matters" summary
|
|
67
|
+
* @param {string} domain - IMPACT_DOMAIN
|
|
68
|
+
* @param {string} severity - SEVERITY_LEVEL
|
|
69
|
+
* @returns {string[]} Array of 1–3 bullets
|
|
70
|
+
*/
|
|
71
|
+
function generateWhyItMatters(domain, severity, breakType = null) {
|
|
72
|
+
const bullets = [];
|
|
73
|
+
|
|
74
|
+
// Domain-specific impact
|
|
75
|
+
if (domain === IMPACT_DOMAINS.REVENUE) {
|
|
76
|
+
bullets.push('🚨 Revenue impact: Checkout/payment flow is broken. Customers cannot complete purchases.');
|
|
77
|
+
} else if (domain === IMPACT_DOMAINS.LEAD) {
|
|
78
|
+
bullets.push('📉 Lead gen impact: Signup/contact flow is broken. Cannot capture customer interest.');
|
|
79
|
+
} else if (domain === IMPACT_DOMAINS.TRUST) {
|
|
80
|
+
bullets.push('⚠️ Trust impact: Auth/account flow is broken. Users cannot access their data.');
|
|
81
|
+
} else {
|
|
82
|
+
bullets.push('📊 UX impact: Core interaction is broken. User journey degraded.');
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Severity escalation
|
|
86
|
+
if (severity === SEVERITY_LEVELS.CRITICAL) {
|
|
87
|
+
bullets.push('🔴 CRITICAL: Escalate immediately. Page/API down or core feature broken.');
|
|
88
|
+
} else if (severity === SEVERITY_LEVELS.WARNING) {
|
|
89
|
+
bullets.push('🟡 WARNING: High priority. Fix before peak traffic to avoid customer impact.');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Phase 5: Visual regression context
|
|
93
|
+
if (breakType === BREAK_TYPES.VISUAL) {
|
|
94
|
+
bullets.push('👁️ Visual regression: UI elements changed from baseline (CSS, layout, or styling).');
|
|
95
|
+
if (severity === SEVERITY_LEVELS.CRITICAL) {
|
|
96
|
+
bullets.push('Critical visual change may completely obscure content or block user interaction.');
|
|
97
|
+
} else if (severity === SEVERITY_LEVELS.WARNING) {
|
|
98
|
+
bullets.push('Visual change may degrade readability, accessibility, or user experience.');
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return bullets;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Generate top 3 actionable next steps
|
|
107
|
+
* @param {string} breakType - BREAK_TYPE
|
|
108
|
+
* @param {string} domain - IMPACT_DOMAIN
|
|
109
|
+
* @returns {string[]} Array of 3 action strings
|
|
110
|
+
*/
|
|
111
|
+
function generateTopActions(breakType, domain) {
|
|
112
|
+
const actions = [];
|
|
113
|
+
|
|
114
|
+
// Break-type-specific actions
|
|
115
|
+
if (breakType === BREAK_TYPES.NAVIGATION || breakType === BREAK_TYPES.NETWORK) {
|
|
116
|
+
actions.push('1. Check server status and network logs for errors');
|
|
117
|
+
actions.push('2. Verify DNS and SSL certificate validity');
|
|
118
|
+
actions.push('3. Check CDN/load balancer for 5xx errors');
|
|
119
|
+
} else if (breakType === BREAK_TYPES.TIMEOUT) {
|
|
120
|
+
actions.push('1. Check server response times and database queries');
|
|
121
|
+
actions.push('2. Review recent deployments for performance regressions');
|
|
122
|
+
actions.push('3. Check if rate limiting is too strict');
|
|
123
|
+
} else if (breakType === BREAK_TYPES.VISUAL) {
|
|
124
|
+
// Phase 5: Visual-specific diagnostic actions
|
|
125
|
+
actions.push('1. Compare baseline screenshot to current; identify CSS/layout changes');
|
|
126
|
+
actions.push('2. Check recent CSS commits, theme changes, or Tailwind/Bootstrap updates');
|
|
127
|
+
actions.push('3. Validate element positioning using browser DevTools layout analysis');
|
|
128
|
+
} else if (breakType === BREAK_TYPES.VALIDATION) {
|
|
129
|
+
actions.push('1. Review frontend code for recent CSS/JS changes');
|
|
130
|
+
actions.push('2. Check browser console for JavaScript errors');
|
|
131
|
+
actions.push('3. Verify DOM selectors match current HTML structure');
|
|
132
|
+
} else if (breakType === BREAK_TYPES.SUBMISSION) {
|
|
133
|
+
actions.push('1. Check form validation rules and error messages');
|
|
134
|
+
actions.push('2. Verify backend API endpoint is reachable');
|
|
135
|
+
actions.push('3. Check for CORS or authentication failures');
|
|
136
|
+
} else if (breakType === BREAK_TYPES.CONSOLE) {
|
|
137
|
+
actions.push('1. Review browser console error logs');
|
|
138
|
+
actions.push('2. Check for third-party script failures');
|
|
139
|
+
actions.push('3. Verify API endpoints and authentication tokens');
|
|
140
|
+
} else {
|
|
141
|
+
actions.push('1. Check application logs for errors');
|
|
142
|
+
actions.push('2. Verify all dependencies are deployed');
|
|
143
|
+
actions.push('3. Check recent changes that might affect this flow');
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return actions;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Aggregate all failures into intelligence summary
|
|
151
|
+
* @param {Array} attempts - Attempt results
|
|
152
|
+
* @param {Array} flows - Flow results
|
|
153
|
+
* @returns {Object} Summary with failures, by-domain counts, escalation signals
|
|
154
|
+
*/
|
|
155
|
+
function aggregateIntelligence(attempts = [], flows = []) {
|
|
156
|
+
const allFailures = [];
|
|
157
|
+
const byDomain = {
|
|
158
|
+
[IMPACT_DOMAINS.REVENUE]: [],
|
|
159
|
+
[IMPACT_DOMAINS.LEAD]: [],
|
|
160
|
+
[IMPACT_DOMAINS.TRUST]: [],
|
|
161
|
+
[IMPACT_DOMAINS.UX]: []
|
|
162
|
+
};
|
|
163
|
+
const bySeverity = {
|
|
164
|
+
[SEVERITY_LEVELS.CRITICAL]: [],
|
|
165
|
+
[SEVERITY_LEVELS.WARNING]: [],
|
|
166
|
+
[SEVERITY_LEVELS.INFO]: []
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
// Analyze attempts
|
|
170
|
+
for (const attempt of attempts) {
|
|
171
|
+
const intel = analyzeFailure(attempt, false);
|
|
172
|
+
if (intel) {
|
|
173
|
+
allFailures.push(intel);
|
|
174
|
+
byDomain[intel.domain].push(intel);
|
|
175
|
+
bySeverity[intel.severity].push(intel);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Analyze flows (higher weight)
|
|
180
|
+
for (const flow of flows) {
|
|
181
|
+
const intel = analyzeFailure(flow, true);
|
|
182
|
+
if (intel) {
|
|
183
|
+
allFailures.push(intel);
|
|
184
|
+
byDomain[intel.domain].push(intel);
|
|
185
|
+
bySeverity[intel.severity].push(intel);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Escalation signals
|
|
190
|
+
const escalationSignals = [];
|
|
191
|
+
if (bySeverity[SEVERITY_LEVELS.CRITICAL].length > 0) {
|
|
192
|
+
escalationSignals.push('CRITICAL failures detected - immediate action required');
|
|
193
|
+
}
|
|
194
|
+
if (byDomain[IMPACT_DOMAINS.REVENUE].length > 0) {
|
|
195
|
+
escalationSignals.push('REVENUE domain affected - financial impact likely');
|
|
196
|
+
}
|
|
197
|
+
if (
|
|
198
|
+
flows.filter(f => f.outcome === 'FAILURE').length > 0 ||
|
|
199
|
+
allFailures.filter(f => f.breakType === BREAK_TYPES.NETWORK || f.breakType === BREAK_TYPES.TIMEOUT).length > 0
|
|
200
|
+
) {
|
|
201
|
+
escalationSignals.push('Infrastructure/availability issue indicated');
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return {
|
|
205
|
+
totalFailures: allFailures.length,
|
|
206
|
+
failures: allFailures,
|
|
207
|
+
byDomain,
|
|
208
|
+
bySeverity,
|
|
209
|
+
escalationSignals,
|
|
210
|
+
criticalCount: bySeverity[SEVERITY_LEVELS.CRITICAL].length,
|
|
211
|
+
warningCount: bySeverity[SEVERITY_LEVELS.WARNING].length,
|
|
212
|
+
infoCount: bySeverity[SEVERITY_LEVELS.INFO].length
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
module.exports = {
|
|
217
|
+
analyzeFailure,
|
|
218
|
+
aggregateIntelligence,
|
|
219
|
+
generateWhyItMatters,
|
|
220
|
+
generateTopActions,
|
|
221
|
+
BREAK_TYPES,
|
|
222
|
+
IMPACT_DOMAINS,
|
|
223
|
+
SEVERITY_LEVELS
|
|
224
|
+
};
|