quality-intelligence-engine 2.2.17 → 2.2.22

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.
Files changed (65) hide show
  1. package/dist/bin/qi.js +8 -3
  2. package/dist/src/adapters/playwright-folder.adapter.js +68 -0
  3. package/dist/src/adapters/playwright-json.adapter.js +46 -0
  4. package/dist/src/adapters/playwright.adapter.js +36 -0
  5. package/dist/src/cli/qi-test.js +20 -0
  6. package/dist/src/cli/qi.js +59 -0
  7. package/dist/src/cli/ui/divider.js +10 -0
  8. package/dist/src/cli/ui/failureLogger.js +24 -0
  9. package/dist/src/configLoader.js +60 -0
  10. package/dist/src/console/issue-view.js +81 -0
  11. package/dist/src/failure-analysis/failure-analyzer.js +38 -0
  12. package/dist/src/final-run.js +131 -0
  13. package/dist/src/final-runner.js +27 -0
  14. package/dist/src/fixtures/networkCollector.js +18 -0
  15. package/dist/src/history/failure-history.store.js +25 -0
  16. package/dist/src/history/failure-history.types.js +4 -0
  17. package/dist/src/history/failure-trend.analyzer.js +31 -0
  18. package/dist/src/index.js +10 -0
  19. package/dist/src/integrations/ci/ci-annotator.js +26 -0
  20. package/dist/src/intelligence/confidence-calibration.engine.js +21 -0
  21. package/dist/src/intelligence/decision-intelligence/confidence.engine.js +16 -0
  22. package/dist/src/intelligence/decision-intelligence/decision.config.js +21 -0
  23. package/dist/src/intelligence/decision-intelligence/decision.engine.js +23 -0
  24. package/dist/src/intelligence/decision-intelligence/decision.types.js +2 -0
  25. package/dist/src/intelligence/failure-fingerprinting/failure.classifier.js +32 -0
  26. package/dist/src/intelligence/failure-fingerprinting/failure.store.js +17 -0
  27. package/dist/src/intelligence/failure-fingerprinting/failure.tracker.js +19 -0
  28. package/dist/src/intelligence/failure-fingerprinting/fingerprint.generator.js +28 -0
  29. package/dist/src/intelligence/failure-fingerprinting/fingerprint.types.js +2 -0
  30. package/dist/src/intelligence/flakiness-intelligence/flakiness.analyzer.js +21 -0
  31. package/dist/src/intelligence/flakiness-intelligence/flakiness.fingerprint.js +16 -0
  32. package/dist/src/intelligence/flakiness-intelligence/flakiness.store.js +24 -0
  33. package/dist/src/intelligence/flakiness-intelligence/flakiness.tracker.js +28 -0
  34. package/dist/src/intelligence/flakiness-intelligence/flakiness.types.js +2 -0
  35. package/dist/src/intelligence/intelligence.pipeline.js +17 -0
  36. package/dist/src/intelligence/llm-explainer.js +19 -0
  37. package/dist/src/intelligence/root-cause/rootcause.engine.js +25 -0
  38. package/dist/src/intelligence/trend-intelligence/trend.engine.js +25 -0
  39. package/dist/src/markdownWriter.js +64 -0
  40. package/dist/src/normalizer.js +17 -0
  41. package/dist/src/passAnalyzer.js +38 -0
  42. package/dist/src/pipeline/ai.summarizer.js +32 -0
  43. package/dist/src/pipeline/failure-analysis.pipeline.js +11 -0
  44. package/dist/src/pipeline/failure-grouping.pipeline.js +59 -0
  45. package/dist/src/playwright/qi.reporter.js +17 -0
  46. package/dist/src/reporter.js +46 -0
  47. package/dist/src/rules.js +32 -0
  48. package/dist/src/runManager.js +19 -0
  49. package/dist/src/runner.js +13 -0
  50. package/dist/src/runtime/networkCollector.js +34 -0
  51. package/dist/src/stackParser.js +17 -0
  52. package/dist/src/test-run.js +48 -0
  53. package/dist/src/types/analysis-result.js +2 -0
  54. package/dist/src/types/failure.types.js +3 -0
  55. package/dist/src/types/playwright-failure.js +2 -0
  56. package/dist/src/types.js +5 -0
  57. package/dist/src/utils/artifact.locator.js +35 -0
  58. package/dist/src/utils/confidence-constants.js +90 -0
  59. package/dist/src/utils/file-utils.js +118 -0
  60. package/dist/src/v2/llm/llm-advisor.js +17 -0
  61. package/dist/src/v2/pipeline/v2-intelligence.pipeline.js +17 -0
  62. package/dist/src/v2/self-healing/self-healer.js +44 -0
  63. package/dist/src/v2/trace-intelligence/trace-analyzer.js +33 -0
  64. package/dist/src/v2-test-run.js +59 -0
  65. package/package.json +1 -1
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ // src/pipeline/failure-grouping.pipeline.ts
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.groupFailures = groupFailures;
5
+ const failure_history_store_1 = require("../history/failure-history.store");
6
+ const failure_trend_analyzer_1 = require("../history/failure-trend.analyzer");
7
+ function groupFailures(results) {
8
+ const groupedCounts = {};
9
+ let flakyCount = 0;
10
+ for (const r of results) {
11
+ const key = r.classification ?? "UNKNOWN";
12
+ groupedCounts[key] = (groupedCounts[key] || 0) + 1;
13
+ if (key === "FLAKY") {
14
+ flakyCount++;
15
+ }
16
+ }
17
+ let dominantCategory = "UNKNOWN";
18
+ let dominantCount = 0;
19
+ for (const [category, count] of Object.entries(groupedCounts)) {
20
+ if (count > dominantCount) {
21
+ dominantCategory = category;
22
+ dominantCount = count;
23
+ }
24
+ }
25
+ /* ===============================
26
+ 🔒 FALLBACK ENFORCEMENT (CRITICAL)
27
+ =============================== */
28
+ if (results.length === 0) {
29
+ groupedCounts["UNCLASSIFIED_FAILURE"] = 1;
30
+ dominantCategory = "UNCLASSIFIED_FAILURE";
31
+ dominantCount = 1;
32
+ }
33
+ const total = Math.max(1, results.length || dominantCount);
34
+ let confidence = dominantCount / total;
35
+ // Ensure non-zero confidence for real failures
36
+ if (dominantCategory === "UNCLASSIFIED_FAILURE" && confidence <= 0) {
37
+ confidence = 0.25;
38
+ }
39
+ // 🔻 FLAKY PENALTY (KEY LOGIC)
40
+ if (flakyCount > 0) {
41
+ const penalty = Math.min(0.3, flakyCount / total);
42
+ confidence = Math.max(0, confidence - penalty);
43
+ }
44
+ const summary = {
45
+ dominantCategory,
46
+ groupedCounts,
47
+ confidence,
48
+ flakyCount
49
+ };
50
+ (0, failure_history_store_1.saveFailureHistory)({
51
+ runId: Date.now().toString(),
52
+ timestamp: new Date().toISOString(),
53
+ dominantCategory,
54
+ groupedCounts,
55
+ confidence
56
+ });
57
+ summary.trend = (0, failure_trend_analyzer_1.analyzeFailureTrends)((0, failure_history_store_1.loadFailureHistory)());
58
+ return summary;
59
+ }
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const failure_tracker_1 = require("../intelligence/failure-fingerprinting/failure.tracker");
4
+ class QIReporter {
5
+ onTestEnd(test, result) {
6
+ if (result.status !== "failed")
7
+ return;
8
+ const errorText = result.error?.message ||
9
+ result.error?.stack ||
10
+ "unknown error";
11
+ (0, failure_tracker_1.trackFailure)({
12
+ error: errorText,
13
+ testName: test.title
14
+ }, process.env.QI_RUN_ID ?? "local-run");
15
+ }
16
+ }
17
+ exports.default = QIReporter;
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.printSummaryAndWriteReports = printSummaryAndWriteReports;
4
+ exports.printPassRisks = printPassRisks;
5
+ const markdownWriter_1 = require("./markdownWriter");
6
+ /**
7
+ * FAILURES: Print summary + write markdown reports
8
+ */
9
+ function printSummaryAndWriteReports(grouped, run, config) {
10
+ let printed = 0;
11
+ grouped.forEach((items, key) => {
12
+ const sample = items[0];
13
+ // Respect confidence threshold
14
+ if (sample.confidence <
15
+ config.engine.confidenceThresholds.fail) {
16
+ return;
17
+ }
18
+ if (printed === 0) {
19
+ console.log(`❌ Failures Detected (${grouped.size} unique issues)\n`);
20
+ }
21
+ printed++;
22
+ console.log(`${printed}) ${sample.category} (${items.length} occurrences)`);
23
+ console.log(` Location : ${sample.location.file}:${sample.location.line}`);
24
+ console.log(` API : ${sample.failedApi.endpoint} → ${sample.failedApi.status}`);
25
+ console.log(` Cause : ${sample.rootCause}`);
26
+ console.log(` Details : output/${run.runDir.split('/').pop()}/${key}/analysis.md\n`);
27
+ (0, markdownWriter_1.writeAnalysisMarkdown)(run.runDir, key, sample, items.length);
28
+ });
29
+ if (printed === 0) {
30
+ console.log('✅ No failures exceeded confidence threshold\n');
31
+ }
32
+ }
33
+ /**
34
+ * PASSES: Print non-blocking risk warnings
35
+ */
36
+ function printPassRisks(risks, _run) {
37
+ if (risks.length === 0)
38
+ return;
39
+ console.log(`⚠️ Pass Risks Detected (${risks.length})\n`);
40
+ risks.forEach((risk, i) => {
41
+ console.log(`${i + 1}) ${risk.test} → ${risk.riskType}`);
42
+ console.log(` Location : ${risk.location.file}`);
43
+ console.log(` Reason : ${risk.reason}`);
44
+ console.log(` Fix : ${risk.fix}\n`);
45
+ });
46
+ }
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateDummyResult = generateDummyResult;
4
+ function generateDummyResult() {
5
+ return {
6
+ category: 'BACKEND_API_FAILURE',
7
+ confidence: 0.93,
8
+ location: {
9
+ file: 'AuthController.java',
10
+ line: 87
11
+ },
12
+ failedApi: {
13
+ method: 'GET',
14
+ endpoint: '/users/{id}',
15
+ status: 404,
16
+ response: 'User not found'
17
+ },
18
+ rootCause: 'The requested user ID does not exist in the database.',
19
+ retryGuidance: 'Automated CI retry is not advised (high confidence application failure).',
20
+ reproductionSteps: [
21
+ 'Start backend service',
22
+ 'Run: curl GET /users/{id}',
23
+ 'Observe: 404 Not Found'
24
+ ],
25
+ expected: 'User details are returned successfully.',
26
+ actual: 'API returns 404 and request fails in AuthController.java:87',
27
+ suggestedActions: [
28
+ 'Validate user existence before API call',
29
+ 'Add graceful handling for missing user records'
30
+ ]
31
+ };
32
+ }
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createRunContext = createRunContext;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ function createRunContext() {
10
+ const now = new Date();
11
+ const runId = now
12
+ .toISOString()
13
+ .replace(/[:.]/g, '-')
14
+ .replace('T', '_')
15
+ .replace('Z', '');
16
+ const runDir = path_1.default.join(process.cwd(), 'output', `run-${runId}`);
17
+ fs_1.default.mkdirSync(runDir, { recursive: true });
18
+ return { runId, runDir };
19
+ }
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ // src/runner.ts
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.runQualityIntelligence = runQualityIntelligence;
5
+ const failure_analysis_pipeline_1 = require("./pipeline/failure-analysis.pipeline");
6
+ const failure_grouping_pipeline_1 = require("./pipeline/failure-grouping.pipeline");
7
+ const intelligence_pipeline_1 = require("./intelligence/intelligence.pipeline");
8
+ async function runQualityIntelligence(input) {
9
+ const analysisResults = await (0, failure_analysis_pipeline_1.runFailureAnalysisFromPlaywright)(input);
10
+ const summary = (0, failure_grouping_pipeline_1.groupFailures)(analysisResults);
11
+ const enriched = await (0, intelligence_pipeline_1.enrichWithIntelligence)(summary);
12
+ return enriched;
13
+ }
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.attachNetworkCollector = attachNetworkCollector;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ function attachNetworkCollector(page, testId) {
10
+ const failures = [];
11
+ page.on('response', response => {
12
+ if (response.status() >= 400) {
13
+ failures.push({
14
+ method: response.request().method(),
15
+ url: new URL(response.url()).pathname,
16
+ status: response.status()
17
+ });
18
+ }
19
+ });
20
+ page.on('requestfailed', request => {
21
+ failures.push({
22
+ method: request.method(),
23
+ url: new URL(request.url()).pathname,
24
+ error: request.failure()?.errorText
25
+ });
26
+ });
27
+ process.on('exit', () => {
28
+ if (failures.length === 0)
29
+ return;
30
+ const dir = path_1.default.join('test-results', testId);
31
+ fs_1.default.mkdirSync(dir, { recursive: true });
32
+ fs_1.default.writeFileSync(path_1.default.join(dir, 'network.json'), JSON.stringify(failures, null, 2));
33
+ });
34
+ }
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseStackTrace = parseStackTrace;
4
+ function parseStackTrace(stack) {
5
+ if (!stack || stack.length === 0) {
6
+ return { file: 'Unknown', line: -1 };
7
+ }
8
+ // Supports formats like: Class.method(File.java:87)
9
+ const match = stack[0].match(/\((.*):(\d+)\)/);
10
+ if (!match) {
11
+ return { file: 'Unknown', line: -1 };
12
+ }
13
+ return {
14
+ file: match[1],
15
+ line: Number(match[2])
16
+ };
17
+ }
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ // src/test-run.ts
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const runner_1 = require("./runner");
5
+ function line(char = "=", count = 60) {
6
+ console.log(char.repeat(count));
7
+ }
8
+ async function main() {
9
+ const playwrightResultsDir = "playwright-results";
10
+ const result = await (0, runner_1.runQualityIntelligence)(playwrightResultsDir);
11
+ line();
12
+ console.log("QUALITY INTELLIGENCE – FINAL OUTPUT");
13
+ line();
14
+ console.log(`Primary Failure : ${result.dominantCategory}`);
15
+ console.log(`Confidence Score : ${result.confidence}`);
16
+ console.log(`Flaky Failures : ${result.flakyCount}`);
17
+ console.log(`Trend Signal : ${result.trend?.signal ?? "N/A"}`);
18
+ line("-");
19
+ console.log("Failure Breakdown:");
20
+ for (const [k, v] of Object.entries(result.groupedCounts)) {
21
+ console.log(` - ${k}: ${v}`);
22
+ }
23
+ line("-");
24
+ console.log("Confidence Diagnosis:");
25
+ for (const lineText of result.intelligence.confidence.explanation) {
26
+ console.log(` • ${lineText}`);
27
+ }
28
+ line("-");
29
+ console.log("AI Explanation:");
30
+ console.log(` Summary: ${result.intelligence.explanation.summary}`);
31
+ if (result.intelligence.explanation.reasoning?.length) {
32
+ console.log(" Reasoning:");
33
+ for (const r of result.intelligence.explanation.reasoning) {
34
+ console.log(` - ${r}`);
35
+ }
36
+ }
37
+ if (result.intelligence.explanation.recommendedAction?.length) {
38
+ console.log(" Recommended Actions:");
39
+ for (const a of result.intelligence.explanation.recommendedAction) {
40
+ console.log(` - ${a}`);
41
+ }
42
+ }
43
+ line();
44
+ }
45
+ main().catch(err => {
46
+ console.error("QUALITY INTELLIGENCE FAILED");
47
+ console.error(err);
48
+ });
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ // src/types/failure.types.ts
3
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ // =====================
3
+ // RAW INPUT TYPES
4
+ // =====================
5
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.locatePlaywrightArtifacts = locatePlaywrightArtifacts;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ function locatePlaywrightArtifacts() {
10
+ const resultsDir = path_1.default.resolve('test-results');
11
+ const screenshots = [];
12
+ let trace;
13
+ if (!fs_1.default.existsSync(resultsDir)) {
14
+ return { screenshots, trace };
15
+ }
16
+ const runDirs = fs_1.default.readdirSync(resultsDir);
17
+ for (const dir of runDirs) {
18
+ const fullDir = path_1.default.join(resultsDir, dir);
19
+ if (!fs_1.default.statSync(fullDir).isDirectory())
20
+ continue;
21
+ const files = fs_1.default.readdirSync(fullDir);
22
+ for (const file of files) {
23
+ const fullPath = path_1.default.join(fullDir, file);
24
+ // 🎥 Trace ZIP (take the latest retry if exists)
25
+ if (file === 'trace.zip') {
26
+ trace = fullPath;
27
+ }
28
+ // 📸 Screenshots
29
+ if (file.endsWith('.png')) {
30
+ screenshots.push(fullPath);
31
+ }
32
+ }
33
+ }
34
+ return { trace, screenshots };
35
+ }
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ /**
3
+ * Confidence Calculation Constants
4
+ *
5
+ * These constants define the base confidence levels and adjustments
6
+ * used throughout the quality intelligence engine.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.TAXONOMY_BASE_CONFIDENCE = exports.CONFIDENCE_THRESHOLDS = exports.CONFIDENCE_BOUNDS = exports.CONFIDENCE_ADJUSTMENTS = exports.BASE_CONFIDENCE = void 0;
10
+ exports.clampConfidence = clampConfidence;
11
+ exports.formatConfidence = formatConfidence;
12
+ /**
13
+ * Base confidence levels for different error types
14
+ */
15
+ exports.BASE_CONFIDENCE = {
16
+ /** Strong backend failure signal (5xx errors) */
17
+ BACKEND_SERVER_ERROR: 0.95,
18
+ /** Backend API failure (any API error) */
19
+ BACKEND_API_ERROR: 0.9,
20
+ /** Test or automation failure */
21
+ TEST_ERROR: 0.75,
22
+ /** Unknown or weak signal */
23
+ UNKNOWN: 0.6,
24
+ };
25
+ /**
26
+ * Confidence adjustments based on test context and signals
27
+ */
28
+ exports.CONFIDENCE_ADJUSTMENTS = {
29
+ /** UI successfully rendered and reached assertion */
30
+ UI_RENDERED: 0.05,
31
+ /** Test involves authentication or login flow */
32
+ AUTH_FLOW_DETECTED: 0.05,
33
+ /** Explicit authentication failure detected */
34
+ EXPLICIT_AUTH_FAILURE: 0.1,
35
+ /** Test involves inventory or data operations */
36
+ DATA_OPERATION_DETECTED: 0.05,
37
+ /** Numeric mismatch detected in assertions */
38
+ NUMERIC_MISMATCH: 0.05,
39
+ };
40
+ /**
41
+ * Maximum and minimum confidence bounds
42
+ */
43
+ exports.CONFIDENCE_BOUNDS = {
44
+ /** Maximum confidence score (never 100% certain) */
45
+ MAX: 0.95,
46
+ /** Minimum confidence score for reporting */
47
+ MIN: 0.5,
48
+ };
49
+ /**
50
+ * Confidence thresholds for decision making
51
+ */
52
+ exports.CONFIDENCE_THRESHOLDS = {
53
+ /** Threshold for blocking CI/CD (high confidence failure) */
54
+ FAIL: 0.85,
55
+ /** Threshold for reporting pass risks */
56
+ PASS_RISK: 0.6,
57
+ /** Threshold for investigating (medium confidence) */
58
+ INVESTIGATE: 0.7,
59
+ /** Threshold for shipping (high confidence in safety) */
60
+ SHIP: 0.85,
61
+ };
62
+ /**
63
+ * Taxonomy rule base confidence levels
64
+ */
65
+ exports.TAXONOMY_BASE_CONFIDENCE = {
66
+ /** Numeric data mismatch */
67
+ NUMERIC_MISMATCH: 0.6,
68
+ /** Authentication failure */
69
+ AUTH_FAILURE: 0.7,
70
+ /** UI visibility issue */
71
+ VISIBILITY: 0.7,
72
+ /** Network timeout */
73
+ TIMEOUT: 0.65,
74
+ /** Element not found */
75
+ ELEMENT_NOT_FOUND: 0.7,
76
+ /** Default fallback */
77
+ DEFAULT: 0.7,
78
+ };
79
+ /**
80
+ * Helper function to clamp confidence within bounds
81
+ */
82
+ function clampConfidence(value) {
83
+ return Math.max(exports.CONFIDENCE_BOUNDS.MIN, Math.min(exports.CONFIDENCE_BOUNDS.MAX, value));
84
+ }
85
+ /**
86
+ * Helper function to format confidence as percentage string
87
+ */
88
+ function formatConfidence(value) {
89
+ return `${(value * 100).toFixed(1)}%`;
90
+ }
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.FileOperationError = void 0;
7
+ exports.readJsonFile = readJsonFile;
8
+ exports.writeJsonFile = writeJsonFile;
9
+ exports.fileExists = fileExists;
10
+ exports.ensureDirectory = ensureDirectory;
11
+ exports.resolvePath = resolvePath;
12
+ const fs_1 = __importDefault(require("fs"));
13
+ const path_1 = __importDefault(require("path"));
14
+ /**
15
+ * Custom error class for file operations
16
+ */
17
+ class FileOperationError extends Error {
18
+ constructor(message, filePath, operation, originalError) {
19
+ super(message);
20
+ this.filePath = filePath;
21
+ this.operation = operation;
22
+ this.originalError = originalError;
23
+ this.name = 'FileOperationError';
24
+ }
25
+ }
26
+ exports.FileOperationError = FileOperationError;
27
+ /**
28
+ * Safely read and parse a JSON file with proper error handling
29
+ * @param filePath - Absolute or relative path to the JSON file
30
+ * @returns Parsed JSON object
31
+ * @throws FileOperationError if file cannot be read or parsed
32
+ */
33
+ function readJsonFile(filePath) {
34
+ try {
35
+ // Check if file exists
36
+ if (!fs_1.default.existsSync(filePath)) {
37
+ throw new FileOperationError(`File not found: ${filePath}`, filePath, 'read');
38
+ }
39
+ // Read file content
40
+ let content;
41
+ try {
42
+ content = fs_1.default.readFileSync(filePath, 'utf-8');
43
+ }
44
+ catch (error) {
45
+ throw new FileOperationError(`Failed to read file: ${filePath}`, filePath, 'read', error);
46
+ }
47
+ // Parse JSON
48
+ try {
49
+ return JSON.parse(content);
50
+ }
51
+ catch (error) {
52
+ throw new FileOperationError(`Invalid JSON in file: ${filePath}`, filePath, 'parse', error);
53
+ }
54
+ }
55
+ catch (error) {
56
+ if (error instanceof FileOperationError) {
57
+ throw error;
58
+ }
59
+ throw new FileOperationError(`Unexpected error reading ${filePath}: ${error.message}`, filePath, 'read', error);
60
+ }
61
+ }
62
+ /**
63
+ * Safely write JSON to a file with proper error handling
64
+ * @param filePath - Absolute or relative path to the JSON file
65
+ * @param data - Data to write (will be JSON.stringified)
66
+ * @param pretty - Whether to pretty-print the JSON (default: true)
67
+ */
68
+ function writeJsonFile(filePath, data, pretty = true) {
69
+ try {
70
+ // Ensure directory exists
71
+ const dir = path_1.default.dirname(filePath);
72
+ if (!fs_1.default.existsSync(dir)) {
73
+ fs_1.default.mkdirSync(dir, { recursive: true });
74
+ }
75
+ // Stringify data
76
+ const content = pretty
77
+ ? JSON.stringify(data, null, 2)
78
+ : JSON.stringify(data);
79
+ // Write to file
80
+ try {
81
+ fs_1.default.writeFileSync(filePath, content, 'utf-8');
82
+ }
83
+ catch (error) {
84
+ throw new FileOperationError(`Failed to write file: ${filePath}`, filePath, 'write', error);
85
+ }
86
+ }
87
+ catch (error) {
88
+ if (error instanceof FileOperationError) {
89
+ throw error;
90
+ }
91
+ throw new FileOperationError(`Unexpected error writing ${filePath}: ${error.message}`, filePath, 'write', error);
92
+ }
93
+ }
94
+ /**
95
+ * Check if a file exists
96
+ * @param filePath - Path to check
97
+ * @returns true if file exists
98
+ */
99
+ function fileExists(filePath) {
100
+ return fs_1.default.existsSync(filePath);
101
+ }
102
+ /**
103
+ * Ensure a directory exists, creating it if necessary
104
+ * @param dirPath - Directory path to ensure
105
+ */
106
+ function ensureDirectory(dirPath) {
107
+ if (!fs_1.default.existsSync(dirPath)) {
108
+ fs_1.default.mkdirSync(dirPath, { recursive: true });
109
+ }
110
+ }
111
+ /**
112
+ * Resolve a path relative to the project root
113
+ * @param relativePath - Path relative to project root
114
+ * @returns Absolute path
115
+ */
116
+ function resolvePath(...segments) {
117
+ return path_1.default.join(process.cwd(), ...segments);
118
+ }
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ // src/v2/llm/llm-advisor.ts
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.getLLMAdvice = getLLMAdvice;
5
+ /**
6
+ * Stub for ChatGPT / Azure / Local LLM
7
+ */
8
+ async function getLLMAdvice(failureSummary) {
9
+ return {
10
+ summary: `AI analysis of failure: ${failureSummary}`,
11
+ fixRecommendation: [
12
+ "Check backend API response",
13
+ "Validate UI rendering timing",
14
+ "Review recent code changes"
15
+ ]
16
+ };
17
+ }
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ // src/v2/pipeline/v2-intelligence.pipeline.ts
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.runV2Intelligence = runV2Intelligence;
5
+ const trace_analyzer_1 = require("../trace-intelligence/trace-analyzer");
6
+ const self_healer_1 = require("../self-healing/self-healer");
7
+ const llm_advisor_1 = require("../llm/llm-advisor");
8
+ async function runV2Intelligence(failureFolder, failureType, errorMessage) {
9
+ const trace = (0, trace_analyzer_1.analyzeTrace)(failureFolder);
10
+ const healing = (0, self_healer_1.attemptSelfHeal)(failureType, errorMessage);
11
+ const llm = await (0, llm_advisor_1.getLLMAdvice)(failureType);
12
+ return {
13
+ trace,
14
+ healing,
15
+ llm
16
+ };
17
+ }
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ // src/v2/self-healing/self-healer.ts
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.attemptSelfHeal = attemptSelfHeal;
5
+ /**
6
+ * Self-Healing Decision Engine (V2)
7
+ * Decides WHAT can be auto-fixed and WHAT should not
8
+ */
9
+ function attemptSelfHeal(failureType, errorMessage) {
10
+ const msg = errorMessage.toLowerCase();
11
+ // 🔁 Flaky tests
12
+ if (failureType === "FLAKY") {
13
+ return {
14
+ reason: "Intermittent retry-based failure detected",
15
+ suggestedFix: "Add proper waits or retry assertions",
16
+ confidence: 0.6
17
+ };
18
+ }
19
+ // 🧭 UI / Locator issues
20
+ if (failureType === "UI_STATE" || failureType === "LOCATOR_CHANGED") {
21
+ return {
22
+ reason: "UI element state or locator changed",
23
+ suggestedFix: "Re-locate element using role/text-based selectors",
24
+ confidence: 0.7
25
+ };
26
+ }
27
+ // 🔢 Numeric mismatch — CONDITIONAL healing
28
+ if (failureType === "NUMERIC_MISMATCH") {
29
+ // UI-level numeric problems (healable)
30
+ if (msg.includes("count") ||
31
+ msg.includes("items") ||
32
+ msg.includes("length") ||
33
+ msg.includes("round")) {
34
+ return {
35
+ reason: "UI count or rounding issue detected",
36
+ suggestedFix: "Update assertion logic or normalize UI values",
37
+ confidence: 0.55
38
+ };
39
+ }
40
+ // Backend/API numeric issues (DO NOT HEAL)
41
+ return null;
42
+ }
43
+ return null;
44
+ }
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ // src/v2/trace-intelligence/trace-analyzer.ts
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.analyzeTrace = analyzeTrace;
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const path_1 = __importDefault(require("path"));
10
+ function analyzeTrace(failureFolder) {
11
+ const fullPath = path_1.default.resolve(failureFolder);
12
+ if (!fs_1.default.existsSync(fullPath)) {
13
+ return {
14
+ page: "UNKNOWN",
15
+ failureStep: "Trace folder not found",
16
+ screenshots: [],
17
+ note: `Missing folder: ${failureFolder}`
18
+ };
19
+ }
20
+ const files = fs_1.default.readdirSync(fullPath);
21
+ const screenshots = files
22
+ .filter(f => f.endsWith(".png") || f.endsWith(".jpg"))
23
+ .map(f => path_1.default.join(fullPath, f));
24
+ const traceFile = files.includes("trace.zip")
25
+ ? path_1.default.join(fullPath, "trace.zip")
26
+ : undefined;
27
+ return {
28
+ page: "UNKNOWN_PAGE",
29
+ failureStep: "Action before failure",
30
+ screenshots,
31
+ traceFile
32
+ };
33
+ }