@yasserkhanorg/e2e-agents 0.3.2
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/LICENSE +168 -0
- package/README.md +620 -0
- package/dist/agent/analysis.d.ts +62 -0
- package/dist/agent/analysis.d.ts.map +1 -0
- package/dist/agent/analysis.js +292 -0
- package/dist/agent/blast_radius.d.ts +4 -0
- package/dist/agent/blast_radius.d.ts.map +1 -0
- package/dist/agent/blast_radius.js +37 -0
- package/dist/agent/cache_utils.d.ts +38 -0
- package/dist/agent/cache_utils.d.ts.map +1 -0
- package/dist/agent/cache_utils.js +67 -0
- package/dist/agent/config.d.ts +148 -0
- package/dist/agent/config.d.ts.map +1 -0
- package/dist/agent/config.js +640 -0
- package/dist/agent/dependency_graph.d.ts +14 -0
- package/dist/agent/dependency_graph.d.ts.map +1 -0
- package/dist/agent/dependency_graph.js +227 -0
- package/dist/agent/feedback.d.ts +55 -0
- package/dist/agent/feedback.d.ts.map +1 -0
- package/dist/agent/feedback.js +257 -0
- package/dist/agent/flags.d.ts +23 -0
- package/dist/agent/flags.d.ts.map +1 -0
- package/dist/agent/flags.js +171 -0
- package/dist/agent/flow_catalog.d.ts +25 -0
- package/dist/agent/flow_catalog.d.ts.map +1 -0
- package/dist/agent/flow_catalog.js +106 -0
- package/dist/agent/flow_mapping.d.ts +10 -0
- package/dist/agent/flow_mapping.d.ts.map +1 -0
- package/dist/agent/flow_mapping.js +84 -0
- package/dist/agent/framework.d.ts +13 -0
- package/dist/agent/framework.d.ts.map +1 -0
- package/dist/agent/framework.js +149 -0
- package/dist/agent/gap_suggestions.d.ts +14 -0
- package/dist/agent/gap_suggestions.d.ts.map +1 -0
- package/dist/agent/gap_suggestions.js +101 -0
- package/dist/agent/generator.d.ts +10 -0
- package/dist/agent/generator.d.ts.map +1 -0
- package/dist/agent/generator.js +115 -0
- package/dist/agent/git.d.ts +11 -0
- package/dist/agent/git.d.ts.map +1 -0
- package/dist/agent/git.js +90 -0
- package/dist/agent/handoff.d.ts +22 -0
- package/dist/agent/handoff.d.ts.map +1 -0
- package/dist/agent/handoff.js +180 -0
- package/dist/agent/impact-analyzer.d.ts +114 -0
- package/dist/agent/impact-analyzer.d.ts.map +1 -0
- package/dist/agent/impact-analyzer.js +557 -0
- package/dist/agent/index.d.ts +21 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +38 -0
- package/dist/agent/model-router.d.ts +57 -0
- package/dist/agent/model-router.d.ts.map +1 -0
- package/dist/agent/model-router.js +154 -0
- package/dist/agent/operational_insights.d.ts +41 -0
- package/dist/agent/operational_insights.d.ts.map +1 -0
- package/dist/agent/operational_insights.js +126 -0
- package/dist/agent/pipeline.d.ts +23 -0
- package/dist/agent/pipeline.d.ts.map +1 -0
- package/dist/agent/pipeline.js +609 -0
- package/dist/agent/plan.d.ts +91 -0
- package/dist/agent/plan.d.ts.map +1 -0
- package/dist/agent/plan.js +331 -0
- package/dist/agent/playwright_report.d.ts +8 -0
- package/dist/agent/playwright_report.d.ts.map +1 -0
- package/dist/agent/playwright_report.js +126 -0
- package/dist/agent/report-generator.d.ts +24 -0
- package/dist/agent/report-generator.d.ts.map +1 -0
- package/dist/agent/report-generator.js +250 -0
- package/dist/agent/report.d.ts +81 -0
- package/dist/agent/report.d.ts.map +1 -0
- package/dist/agent/report.js +147 -0
- package/dist/agent/runner.d.ts +7 -0
- package/dist/agent/runner.d.ts.map +1 -0
- package/dist/agent/runner.js +576 -0
- package/dist/agent/selectors.d.ts +10 -0
- package/dist/agent/selectors.d.ts.map +1 -0
- package/dist/agent/selectors.js +75 -0
- package/dist/agent/spec-bridge.d.ts +101 -0
- package/dist/agent/spec-bridge.d.ts.map +1 -0
- package/dist/agent/spec-bridge.js +273 -0
- package/dist/agent/spec-builder.d.ts +102 -0
- package/dist/agent/spec-builder.d.ts.map +1 -0
- package/dist/agent/spec-builder.js +273 -0
- package/dist/agent/subsystem_risk.d.ts +23 -0
- package/dist/agent/subsystem_risk.d.ts.map +1 -0
- package/dist/agent/subsystem_risk.js +207 -0
- package/dist/agent/telemetry.d.ts +84 -0
- package/dist/agent/telemetry.d.ts.map +1 -0
- package/dist/agent/telemetry.js +220 -0
- package/dist/agent/test_path.d.ts +2 -0
- package/dist/agent/test_path.d.ts.map +1 -0
- package/dist/agent/test_path.js +23 -0
- package/dist/agent/tests.d.ts +18 -0
- package/dist/agent/tests.d.ts.map +1 -0
- package/dist/agent/tests.js +106 -0
- package/dist/agent/traceability.d.ts +22 -0
- package/dist/agent/traceability.d.ts.map +1 -0
- package/dist/agent/traceability.js +183 -0
- package/dist/agent/traceability_capture.d.ts +18 -0
- package/dist/agent/traceability_capture.d.ts.map +1 -0
- package/dist/agent/traceability_capture.js +313 -0
- package/dist/agent/traceability_ingest.d.ts +21 -0
- package/dist/agent/traceability_ingest.d.ts.map +1 -0
- package/dist/agent/traceability_ingest.js +237 -0
- package/dist/agent/utils.d.ts +13 -0
- package/dist/agent/utils.d.ts.map +1 -0
- package/dist/agent/utils.js +152 -0
- package/dist/agent/validators/selector-validator.d.ts +74 -0
- package/dist/agent/validators/selector-validator.d.ts.map +1 -0
- package/dist/agent/validators/selector-validator.js +165 -0
- package/dist/anthropic_provider.d.ts +65 -0
- package/dist/anthropic_provider.d.ts.map +1 -0
- package/dist/anthropic_provider.js +332 -0
- package/dist/api.d.ts +48 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +113 -0
- package/dist/base_provider.d.ts +53 -0
- package/dist/base_provider.d.ts.map +1 -0
- package/dist/base_provider.js +81 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +843 -0
- package/dist/custom_provider.d.ts +20 -0
- package/dist/custom_provider.d.ts.map +1 -0
- package/dist/custom_provider.js +276 -0
- package/dist/e2e-test-gen/index.d.ts +51 -0
- package/dist/e2e-test-gen/index.d.ts.map +1 -0
- package/dist/e2e-test-gen/index.js +57 -0
- package/dist/e2e-test-gen/spec_parser.d.ts +142 -0
- package/dist/e2e-test-gen/spec_parser.d.ts.map +1 -0
- package/dist/e2e-test-gen/spec_parser.js +786 -0
- package/dist/e2e-test-gen/types.d.ts +185 -0
- package/dist/e2e-test-gen/types.d.ts.map +1 -0
- package/dist/e2e-test-gen/types.js +4 -0
- package/dist/esm/agent/analysis.js +287 -0
- package/dist/esm/agent/blast_radius.js +34 -0
- package/dist/esm/agent/cache_utils.js +63 -0
- package/dist/esm/agent/config.js +637 -0
- package/dist/esm/agent/dependency_graph.js +224 -0
- package/dist/esm/agent/feedback.js +253 -0
- package/dist/esm/agent/flags.js +160 -0
- package/dist/esm/agent/flow_catalog.js +103 -0
- package/dist/esm/agent/flow_mapping.js +81 -0
- package/dist/esm/agent/framework.js +145 -0
- package/dist/esm/agent/gap_suggestions.js +98 -0
- package/dist/esm/agent/generator.js +112 -0
- package/dist/esm/agent/git.js +87 -0
- package/dist/esm/agent/handoff.js +177 -0
- package/dist/esm/agent/impact-analyzer.js +548 -0
- package/dist/esm/agent/index.js +22 -0
- package/dist/esm/agent/model-router.js +150 -0
- package/dist/esm/agent/operational_insights.js +123 -0
- package/dist/esm/agent/pipeline.js +605 -0
- package/dist/esm/agent/plan.js +324 -0
- package/dist/esm/agent/playwright_report.js +123 -0
- package/dist/esm/agent/report-generator.js +247 -0
- package/dist/esm/agent/report.js +144 -0
- package/dist/esm/agent/runner.js +572 -0
- package/dist/esm/agent/selectors.js +71 -0
- package/dist/esm/agent/spec-bridge.js +267 -0
- package/dist/esm/agent/spec-builder.js +267 -0
- package/dist/esm/agent/subsystem_risk.js +204 -0
- package/dist/esm/agent/telemetry.js +216 -0
- package/dist/esm/agent/test_path.js +20 -0
- package/dist/esm/agent/tests.js +101 -0
- package/dist/esm/agent/traceability.js +180 -0
- package/dist/esm/agent/traceability_capture.js +310 -0
- package/dist/esm/agent/traceability_ingest.js +234 -0
- package/dist/esm/agent/utils.js +138 -0
- package/dist/esm/agent/validators/selector-validator.js +160 -0
- package/dist/esm/anthropic_provider.js +324 -0
- package/dist/esm/api.js +105 -0
- package/dist/esm/base_provider.js +77 -0
- package/dist/esm/cli.js +841 -0
- package/dist/esm/custom_provider.js +272 -0
- package/dist/esm/e2e-test-gen/index.js +50 -0
- package/dist/esm/e2e-test-gen/spec_parser.js +782 -0
- package/dist/esm/e2e-test-gen/types.js +3 -0
- package/dist/esm/index.js +16 -0
- package/dist/esm/logger.js +89 -0
- package/dist/esm/mcp-server.js +465 -0
- package/dist/esm/ollama_provider.js +300 -0
- package/dist/esm/openai_provider.js +242 -0
- package/dist/esm/package.json +3 -0
- package/dist/esm/plan-and-test-constants.js +126 -0
- package/dist/esm/provider_factory.js +336 -0
- package/dist/esm/provider_interface.js +23 -0
- package/dist/esm/provider_utils.js +96 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +41 -0
- package/dist/logger.d.ts +23 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +93 -0
- package/dist/mcp-server.d.ts +35 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +469 -0
- package/dist/ollama_provider.d.ts +65 -0
- package/dist/ollama_provider.d.ts.map +1 -0
- package/dist/ollama_provider.js +308 -0
- package/dist/openai_provider.d.ts +23 -0
- package/dist/openai_provider.d.ts.map +1 -0
- package/dist/openai_provider.js +250 -0
- package/dist/plan-and-test-constants.d.ts +110 -0
- package/dist/plan-and-test-constants.d.ts.map +1 -0
- package/dist/plan-and-test-constants.js +132 -0
- package/dist/provider_factory.d.ts +99 -0
- package/dist/provider_factory.d.ts.map +1 -0
- package/dist/provider_factory.js +341 -0
- package/dist/provider_interface.d.ts +358 -0
- package/dist/provider_interface.d.ts.map +1 -0
- package/dist/provider_interface.js +28 -0
- package/dist/provider_utils.d.ts +39 -0
- package/dist/provider_utils.d.ts.map +1 -0
- package/dist/provider_utils.js +103 -0
- package/package.json +101 -0
- package/schemas/gap.schema.json +18 -0
- package/schemas/impact.schema.json +418 -0
- package/schemas/plan.schema.json +285 -0
- package/schemas/subsystem-risk-map.schema.json +62 -0
- package/schemas/traceability-input.schema.json +122 -0
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
3
|
+
// See LICENSE.txt for license information.
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.ModelRouter = void 0;
|
|
6
|
+
const MODEL_RATES = {
|
|
7
|
+
'claude-haiku-4-0-20250430': 0.25 / 1000000,
|
|
8
|
+
'claude-sonnet-4-5-20250929': 3 / 1000000,
|
|
9
|
+
'claude-opus-4-6-20250820': 15 / 1000000,
|
|
10
|
+
};
|
|
11
|
+
class ModelRouter {
|
|
12
|
+
constructor(config = {}) {
|
|
13
|
+
this.modelConfig = {
|
|
14
|
+
simpleModel: config.simpleModel || 'claude-haiku-4-0-20250430',
|
|
15
|
+
moderateModel: config.moderateModel || 'claude-sonnet-4-5-20250929',
|
|
16
|
+
complexModel: config.complexModel || 'claude-opus-4-6-20250820',
|
|
17
|
+
criticalModel: config.criticalModel || 'claude-opus-4-6-20250820',
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Classify task complexity based on operation, attempt number, and context
|
|
22
|
+
*/
|
|
23
|
+
classifyTask(context) {
|
|
24
|
+
// Healing: Haiku for attempts 1-2, Sonnet for attempt 3
|
|
25
|
+
if (context.operation === 'heal') {
|
|
26
|
+
if (context.attemptNumber && context.attemptNumber <= 2) {
|
|
27
|
+
// First two healing attempts use simple classification
|
|
28
|
+
return {
|
|
29
|
+
type: 'simple',
|
|
30
|
+
confidence: 95,
|
|
31
|
+
reasoning: `Healing attempt ${context.attemptNumber}/3 - re-exploration with targeted fixes`,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
// Final healing attempt is more complex
|
|
35
|
+
return {
|
|
36
|
+
type: 'moderate',
|
|
37
|
+
confidence: 90,
|
|
38
|
+
reasoning: 'Final healing attempt - may need comprehensive refactoring',
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
// Validation: Always simple (use Haiku)
|
|
42
|
+
if (context.operation === 'validate') {
|
|
43
|
+
return {
|
|
44
|
+
type: 'simple',
|
|
45
|
+
confidence: 100,
|
|
46
|
+
reasoning: 'Selector/code validation is lightweight',
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
// Scoring: Simple (quick analysis)
|
|
50
|
+
if (context.operation === 'score') {
|
|
51
|
+
return {
|
|
52
|
+
type: 'simple',
|
|
53
|
+
confidence: 95,
|
|
54
|
+
reasoning: 'Test quality scoring via static analysis',
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
// Exploration: Simple (just navigation and snapshot)
|
|
58
|
+
if (context.operation === 'explore') {
|
|
59
|
+
return {
|
|
60
|
+
type: 'simple',
|
|
61
|
+
confidence: 90,
|
|
62
|
+
reasoning: 'UI exploration is mostly navigation',
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
// Generation: Varies by UI map coverage
|
|
66
|
+
if (context.operation === 'generate') {
|
|
67
|
+
// Strong signal: Use Sonnet but can optimize
|
|
68
|
+
if (context.uiMapCoverage && context.uiMapCoverage >= 75) {
|
|
69
|
+
return {
|
|
70
|
+
type: 'moderate',
|
|
71
|
+
confidence: 90,
|
|
72
|
+
reasoning: `Strong UI signal (${context.uiMapCoverage}% coverage) - moderate complexity generation`,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
// Moderate signal: Use Sonnet
|
|
76
|
+
if (context.uiMapCoverage && context.uiMapCoverage >= 50) {
|
|
77
|
+
return {
|
|
78
|
+
type: 'moderate',
|
|
79
|
+
confidence: 75,
|
|
80
|
+
reasoning: `Moderate UI signal (${context.uiMapCoverage}% coverage) - standard generation`,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
// Weak signal: Complex task (need better reasoning)
|
|
84
|
+
if (context.uiMapCoverage && context.uiMapCoverage < 50) {
|
|
85
|
+
return {
|
|
86
|
+
type: 'complex',
|
|
87
|
+
confidence: 70,
|
|
88
|
+
reasoning: `Weak UI signal (${context.uiMapCoverage}% coverage) - requires advanced reasoning`,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
// Unknown coverage: Assume moderate
|
|
92
|
+
return {
|
|
93
|
+
type: 'moderate',
|
|
94
|
+
confidence: 50,
|
|
95
|
+
reasoning: 'Generation with unknown UI coverage - use standard model',
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
// Default to moderate
|
|
99
|
+
return {
|
|
100
|
+
type: 'moderate',
|
|
101
|
+
confidence: 50,
|
|
102
|
+
reasoning: 'Unknown operation - defaulting to moderate complexity',
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Select appropriate model based on task complexity
|
|
107
|
+
*/
|
|
108
|
+
selectModel(complexity) {
|
|
109
|
+
switch (complexity.type) {
|
|
110
|
+
case 'simple':
|
|
111
|
+
return this.modelConfig.simpleModel;
|
|
112
|
+
case 'moderate':
|
|
113
|
+
return this.modelConfig.moderateModel;
|
|
114
|
+
case 'complex':
|
|
115
|
+
return this.modelConfig.complexModel;
|
|
116
|
+
case 'critical':
|
|
117
|
+
return this.modelConfig.criticalModel;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Get estimated cost for a task
|
|
122
|
+
*/
|
|
123
|
+
estimateCost(complexity, estimatedTokens = 5000) {
|
|
124
|
+
const model = this.selectModel(complexity);
|
|
125
|
+
const rate = MODEL_RATES[model] || 0.003 / 1000000;
|
|
126
|
+
return estimatedTokens * rate;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Get cost savings vs always using Sonnet
|
|
130
|
+
*/
|
|
131
|
+
estimateSavings(complexity, estimatedTokens = 5000) {
|
|
132
|
+
const selectedModel = this.selectModel(complexity);
|
|
133
|
+
const selectedRate = MODEL_RATES[selectedModel] || 0.003 / 1000000;
|
|
134
|
+
const sonnetRate = MODEL_RATES['claude-sonnet-4-5-20250929'];
|
|
135
|
+
const selectedCost = estimatedTokens * selectedRate;
|
|
136
|
+
const sonnetCost = estimatedTokens * sonnetRate;
|
|
137
|
+
const savedCost = sonnetCost - selectedCost;
|
|
138
|
+
const savingsPercent = (savedCost / sonnetCost) * 100;
|
|
139
|
+
return { savedCost, savingsPercent };
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Format complexity for logging
|
|
143
|
+
*/
|
|
144
|
+
formatComplexity(complexity, tokensUsed) {
|
|
145
|
+
const model = this.selectModel(complexity);
|
|
146
|
+
const modelShort = model.includes('haiku') ? 'Haiku' : model.includes('sonnet') ? 'Sonnet' : 'Opus';
|
|
147
|
+
const confidence = `${complexity.confidence}%`;
|
|
148
|
+
const cost = tokensUsed
|
|
149
|
+
? ` ($${(tokensUsed * (MODEL_RATES[model] || 0)).toFixed(4)})`
|
|
150
|
+
: '';
|
|
151
|
+
return `${complexity.type.toUpperCase()}/${modelShort}/${confidence}${cost} - ${complexity.reasoning}`;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
exports.ModelRouter = ModelRouter;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { PlanReport } from './plan.js';
|
|
2
|
+
import type { CalibrationSummary } from './feedback.js';
|
|
3
|
+
export interface FlakyTestRecord {
|
|
4
|
+
test: string;
|
|
5
|
+
flakeRate: number;
|
|
6
|
+
flakeRate7d?: number;
|
|
7
|
+
flakeRate30d?: number;
|
|
8
|
+
trend?: 'up' | 'down' | 'stable';
|
|
9
|
+
subsystem?: string;
|
|
10
|
+
owners?: string[];
|
|
11
|
+
quarantine?: boolean;
|
|
12
|
+
quarantineState?: 'none' | 'active' | 'retire-candidate';
|
|
13
|
+
lastFailureAt?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface FlakyManifest {
|
|
16
|
+
schemaVersion?: string;
|
|
17
|
+
tests: FlakyTestRecord[];
|
|
18
|
+
}
|
|
19
|
+
export interface QualityGateRecord {
|
|
20
|
+
name: string;
|
|
21
|
+
status: 'pass' | 'warn' | 'fail';
|
|
22
|
+
details?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface QualityGateManifest {
|
|
25
|
+
schemaVersion?: string;
|
|
26
|
+
gates: QualityGateRecord[];
|
|
27
|
+
}
|
|
28
|
+
export interface OperationalInsights {
|
|
29
|
+
flaky?: {
|
|
30
|
+
highRiskRecommendedTests: FlakyTestRecord[];
|
|
31
|
+
quarantinedRecommendedTests: string[];
|
|
32
|
+
ownerMentions?: string[];
|
|
33
|
+
};
|
|
34
|
+
qualityGates?: {
|
|
35
|
+
failed: QualityGateRecord[];
|
|
36
|
+
warnings: QualityGateRecord[];
|
|
37
|
+
};
|
|
38
|
+
calibration?: CalibrationSummary['overall'];
|
|
39
|
+
}
|
|
40
|
+
export declare function applyOperationalInsights(plan: PlanReport, appRoot: string): PlanReport;
|
|
41
|
+
//# sourceMappingURL=operational_insights.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operational_insights.d.ts","sourceRoot":"","sources":["../../src/agent/operational_insights.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,WAAW,CAAC;AAC1C,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAGtD,MAAM,WAAW,eAAe;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,QAAQ,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,kBAAkB,CAAC;IACzD,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,eAAe,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,iBAAiB;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAChC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,iBAAiB,EAAE,CAAC;CAC9B;AAED,MAAM,WAAW,mBAAmB;IAChC,KAAK,CAAC,EAAE;QACJ,wBAAwB,EAAE,eAAe,EAAE,CAAC;QAC5C,2BAA2B,EAAE,MAAM,EAAE,CAAC;QACtC,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;KAC5B,CAAC;IACF,YAAY,CAAC,EAAE;QACX,MAAM,EAAE,iBAAiB,EAAE,CAAC;QAC5B,QAAQ,EAAE,iBAAiB,EAAE,CAAC;KACjC,CAAC;IACF,WAAW,CAAC,EAAE,kBAAkB,CAAC,SAAS,CAAC,CAAC;CAC/C;AA2CD,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,GAAG,UAAU,CA4FtF"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
3
|
+
// See LICENSE.txt for license information.
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.applyOperationalInsights = applyOperationalInsights;
|
|
6
|
+
const fs_1 = require("fs");
|
|
7
|
+
const path_1 = require("path");
|
|
8
|
+
const test_path_js_1 = require("./test_path.js");
|
|
9
|
+
function readJson(path) {
|
|
10
|
+
if (!(0, fs_1.existsSync)(path)) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
try {
|
|
14
|
+
return JSON.parse((0, fs_1.readFileSync)(path, 'utf-8'));
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function normalizeTestName(test) {
|
|
21
|
+
return test.replace(/ \(flags:.*\)$/, '').trim();
|
|
22
|
+
}
|
|
23
|
+
function subsystemForTest(test) {
|
|
24
|
+
return (0, test_path_js_1.inferSubsystemFromTestPath)(test);
|
|
25
|
+
}
|
|
26
|
+
function riskyRate(entry) {
|
|
27
|
+
if (entry.flakeRate30d !== undefined) {
|
|
28
|
+
return entry.flakeRate30d;
|
|
29
|
+
}
|
|
30
|
+
return entry.flakeRate;
|
|
31
|
+
}
|
|
32
|
+
function loadFlakyManifest(appRoot) {
|
|
33
|
+
const path = (0, path_1.join)(appRoot, '.e2e-ai-agents', 'flaky-tests.json');
|
|
34
|
+
return readJson(path);
|
|
35
|
+
}
|
|
36
|
+
function loadQualityGates(appRoot) {
|
|
37
|
+
const path = (0, path_1.join)(appRoot, '.e2e-ai-agents', 'quality-gates.json');
|
|
38
|
+
return readJson(path);
|
|
39
|
+
}
|
|
40
|
+
function loadCalibration(appRoot) {
|
|
41
|
+
const path = (0, path_1.join)(appRoot, '.e2e-ai-agents', 'calibration.json');
|
|
42
|
+
return readJson(path);
|
|
43
|
+
}
|
|
44
|
+
function applyOperationalInsights(plan, appRoot) {
|
|
45
|
+
const enhanced = { ...plan };
|
|
46
|
+
const insights = {};
|
|
47
|
+
const flaky = loadFlakyManifest(appRoot);
|
|
48
|
+
if (flaky && Array.isArray(flaky.tests)) {
|
|
49
|
+
const recommended = new Set(plan.recommendedTests.map(normalizeTestName));
|
|
50
|
+
const risky = flaky.tests
|
|
51
|
+
.filter((entry) => recommended.has(normalizeTestName(entry.test)) && riskyRate(entry) >= 0.2)
|
|
52
|
+
.sort((a, b) => riskyRate(b) - riskyRate(a))
|
|
53
|
+
.slice(0, 10);
|
|
54
|
+
const quarantined = risky.filter((entry) => entry.quarantine).map((entry) => entry.test);
|
|
55
|
+
const owners = Array.from(new Set(risky
|
|
56
|
+
.flatMap((entry) => entry.owners || [])
|
|
57
|
+
.filter(Boolean)));
|
|
58
|
+
insights.flaky = {
|
|
59
|
+
highRiskRecommendedTests: risky,
|
|
60
|
+
quarantinedRecommendedTests: quarantined,
|
|
61
|
+
ownerMentions: owners,
|
|
62
|
+
};
|
|
63
|
+
if (quarantined.length > 0) {
|
|
64
|
+
enhanced.reasons = [...enhanced.reasons, `Quarantined flaky tests in recommendation: ${quarantined.join(', ')}`];
|
|
65
|
+
}
|
|
66
|
+
if (owners.length > 0) {
|
|
67
|
+
enhanced.reasons = [...enhanced.reasons, `Subsystem owners to notify for flaky risk: ${owners.join(', ')}`];
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
const gates = loadQualityGates(appRoot);
|
|
71
|
+
if (gates && Array.isArray(gates.gates)) {
|
|
72
|
+
const failed = gates.gates.filter((gate) => gate.status === 'fail');
|
|
73
|
+
const warnings = gates.gates.filter((gate) => gate.status === 'warn');
|
|
74
|
+
insights.qualityGates = { failed, warnings };
|
|
75
|
+
if (failed.length > 0 && enhanced.runSet !== 'full') {
|
|
76
|
+
enhanced.runSet = 'full';
|
|
77
|
+
enhanced.reasons = [...enhanced.reasons, `Quality gates failed: ${failed.map((gate) => gate.name).join(', ')}`];
|
|
78
|
+
enhanced.policy.triggeredRules = [...new Set([...enhanced.policy.triggeredRules, 'quality-gate-failed'])];
|
|
79
|
+
enhanced.decision = {
|
|
80
|
+
action: 'run-now',
|
|
81
|
+
title: 'Run now',
|
|
82
|
+
summary: 'Quality gate failures detected. Full suite is required before merge.',
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const calibration = loadCalibration(appRoot);
|
|
87
|
+
if (calibration) {
|
|
88
|
+
insights.calibration = calibration.overall;
|
|
89
|
+
if (calibration.overall.falseNegativeRate >= 0.2 && enhanced.runSet !== 'full') {
|
|
90
|
+
enhanced.runSet = 'full';
|
|
91
|
+
enhanced.reasons = [...enhanced.reasons, 'Historical false-negative rate is high; escalating to full suite.'];
|
|
92
|
+
enhanced.policy.triggeredRules = [...new Set([...enhanced.policy.triggeredRules, 'historical-fnr-high'])];
|
|
93
|
+
}
|
|
94
|
+
const recommendedSubsystems = Array.from(new Set(plan.recommendedTests.map(subsystemForTest)));
|
|
95
|
+
const highRiskSubsystems = recommendedSubsystems
|
|
96
|
+
.map((subsystem) => {
|
|
97
|
+
const metric = calibration.bySubsystem[subsystem];
|
|
98
|
+
if (!metric) {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
if (metric.samples < 5) {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
if (metric.recent30d.falseNegativeRate >= 0.2 || metric.falseNegativeRate >= 0.25) {
|
|
105
|
+
return { subsystem, fnr: metric.recent30d.falseNegativeRate || metric.falseNegativeRate };
|
|
106
|
+
}
|
|
107
|
+
return null;
|
|
108
|
+
})
|
|
109
|
+
.filter(Boolean);
|
|
110
|
+
if (highRiskSubsystems.length > 0 && enhanced.runSet !== 'full') {
|
|
111
|
+
enhanced.runSet = 'full';
|
|
112
|
+
enhanced.reasons = [
|
|
113
|
+
...enhanced.reasons,
|
|
114
|
+
`Historical subsystem false-negative risk is high: ${highRiskSubsystems.map((entry) => `${entry.subsystem}(${entry.fnr})`).join(', ')}`,
|
|
115
|
+
];
|
|
116
|
+
enhanced.policy.triggeredRules = [...new Set([...enhanced.policy.triggeredRules, 'subsystem-fnr-high'])];
|
|
117
|
+
enhanced.decision = {
|
|
118
|
+
action: 'run-now',
|
|
119
|
+
title: 'Run now',
|
|
120
|
+
summary: 'Subsystem calibration risk is high. Full suite is required before merge.',
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
enhanced.insights = insights;
|
|
125
|
+
return enhanced;
|
|
126
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { PipelineConfig } from './config.js';
|
|
2
|
+
import type { FlowImpact } from './analysis.js';
|
|
3
|
+
export interface PipelineResult {
|
|
4
|
+
flowId: string;
|
|
5
|
+
flowName: string;
|
|
6
|
+
generatedDir: string;
|
|
7
|
+
generateStatus: 'success' | 'skipped' | 'failed';
|
|
8
|
+
healStatus?: 'success' | 'skipped' | 'failed';
|
|
9
|
+
error?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface PipelineSummary {
|
|
12
|
+
runner: 'e2e-test-gen' | 'package-native' | 'unknown';
|
|
13
|
+
results: PipelineResult[];
|
|
14
|
+
warnings: string[];
|
|
15
|
+
}
|
|
16
|
+
export interface SpecHealTarget {
|
|
17
|
+
specPath: string;
|
|
18
|
+
status?: 'failed' | 'flaky';
|
|
19
|
+
reason?: string;
|
|
20
|
+
}
|
|
21
|
+
export declare function runTargetedSpecHeal(testsRoot: string, targets: SpecHealTarget[], pipeline: PipelineConfig): PipelineSummary;
|
|
22
|
+
export declare function runPlaywrightPipeline(testsRoot: string, flows: FlowImpact[], pipeline: PipelineConfig): PipelineSummary;
|
|
23
|
+
//# sourceMappingURL=pipeline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../src/agent/pipeline.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,eAAe,CAAC;AAG9C,MAAM,WAAW,cAAc;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;IACjD,UAAU,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;IAC9C,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC5B,MAAM,EAAE,cAAc,GAAG,gBAAgB,GAAG,SAAS,CAAC;IACtD,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,QAAQ,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAmeD,wBAAgB,mBAAmB,CAC/B,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,cAAc,EAAE,EACzB,QAAQ,EAAE,cAAc,GACzB,eAAe,CAsFjB;AAwBD,wBAAgB,qBAAqB,CACjC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,UAAU,EAAE,EACnB,QAAQ,EAAE,cAAc,GACzB,eAAe,CAyHjB"}
|