@yasserkhanorg/e2e-agents 1.7.7 → 1.8.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/README.md +55 -0
- package/dist/agent/git.d.ts +5 -0
- package/dist/agent/git.d.ts.map +1 -1
- package/dist/agent/git.js +13 -0
- package/dist/agents/coverage-evaluator.d.ts +8 -0
- package/dist/agents/coverage-evaluator.d.ts.map +1 -0
- package/dist/agents/coverage-evaluator.js +41 -0
- package/dist/agents/cross-impact.d.ts +13 -0
- package/dist/agents/cross-impact.d.ts.map +1 -0
- package/dist/agents/cross-impact.js +135 -0
- package/dist/agents/executor.d.ts +8 -0
- package/dist/agents/executor.d.ts.map +1 -0
- package/dist/agents/executor.js +70 -0
- package/dist/agents/explorer.d.ts +12 -0
- package/dist/agents/explorer.d.ts.map +1 -0
- package/dist/agents/explorer.js +43 -0
- package/dist/agents/generator.d.ts +8 -0
- package/dist/agents/generator.d.ts.map +1 -0
- package/dist/agents/generator.js +77 -0
- package/dist/agents/healer.d.ts +8 -0
- package/dist/agents/healer.d.ts.map +1 -0
- package/dist/agents/healer.js +31 -0
- package/dist/agents/impact-analyst.d.ts +8 -0
- package/dist/agents/impact-analyst.d.ts.map +1 -0
- package/dist/agents/impact-analyst.js +38 -0
- package/dist/agents/regression-advisor.d.ts +8 -0
- package/dist/agents/regression-advisor.d.ts.map +1 -0
- package/dist/agents/regression-advisor.js +116 -0
- package/dist/agents/strategist.d.ts +9 -0
- package/dist/agents/strategist.d.ts.map +1 -0
- package/dist/agents/strategist.js +87 -0
- package/dist/agents/test-designer.d.ts +8 -0
- package/dist/agents/test-designer.d.ts.map +1 -0
- package/dist/agents/test-designer.js +106 -0
- package/dist/cli/commands/crew.d.ts +3 -0
- package/dist/cli/commands/crew.d.ts.map +1 -0
- package/dist/cli/commands/crew.js +137 -0
- package/dist/cli/parse_args.d.ts.map +1 -1
- package/dist/cli/parse_args.js +2 -1
- package/dist/cli/types.d.ts +2 -1
- package/dist/cli/types.d.ts.map +1 -1
- package/dist/cli.js +5 -0
- package/dist/crew/context.d.ts +40 -0
- package/dist/crew/context.d.ts.map +1 -0
- package/dist/crew/context.js +36 -0
- package/dist/crew/orchestrator.d.ts +36 -0
- package/dist/crew/orchestrator.d.ts.map +1 -0
- package/dist/crew/orchestrator.js +171 -0
- package/dist/crew/protocol.d.ts +33 -0
- package/dist/crew/protocol.d.ts.map +1 -0
- package/dist/crew/protocol.js +4 -0
- package/dist/crew/provider.d.ts +3 -0
- package/dist/crew/provider.d.ts.map +1 -0
- package/dist/crew/provider.js +16 -0
- package/dist/crew/sanitize.d.ts +3 -0
- package/dist/crew/sanitize.d.ts.map +1 -0
- package/dist/crew/sanitize.js +31 -0
- package/dist/crew/types.d.ts +52 -0
- package/dist/crew/types.d.ts.map +1 -0
- package/dist/crew/types.js +4 -0
- package/dist/crew/workflows.d.ts +52 -0
- package/dist/crew/workflows.d.ts.map +1 -0
- package/dist/crew/workflows.js +36 -0
- package/dist/esm/agent/git.js +12 -0
- package/dist/esm/agents/coverage-evaluator.js +37 -0
- package/dist/esm/agents/cross-impact.js +131 -0
- package/dist/esm/agents/executor.js +66 -0
- package/dist/esm/agents/explorer.js +39 -0
- package/dist/esm/agents/generator.js +73 -0
- package/dist/esm/agents/healer.js +27 -0
- package/dist/esm/agents/impact-analyst.js +34 -0
- package/dist/esm/agents/regression-advisor.js +112 -0
- package/dist/esm/agents/strategist.js +83 -0
- package/dist/esm/agents/test-designer.js +102 -0
- package/dist/esm/cli/commands/crew.js +134 -0
- package/dist/esm/cli/parse_args.js +2 -1
- package/dist/esm/cli.js +5 -0
- package/dist/esm/crew/context.js +32 -0
- package/dist/esm/crew/orchestrator.js +167 -0
- package/dist/esm/crew/protocol.js +3 -0
- package/dist/esm/crew/provider.js +13 -0
- package/dist/esm/crew/sanitize.js +27 -0
- package/dist/esm/crew/types.js +3 -0
- package/dist/esm/crew/workflows.js +33 -0
- package/dist/esm/index.js +14 -0
- package/dist/esm/knowledge/route_families.js +2 -2
- package/dist/esm/logger.js +1 -2
- package/dist/esm/ollama_provider.js +1 -1
- package/dist/esm/prompts/cross-impact.js +71 -0
- package/dist/esm/prompts/strategist.js +79 -0
- package/dist/esm/prompts/test-designer.js +107 -0
- package/dist/esm/provider_factory.js +6 -10
- package/dist/esm/training/enricher.js +4 -3
- package/dist/esm/training/validator.js +2 -1
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +27 -1
- package/dist/knowledge/route_families.d.ts.map +1 -1
- package/dist/knowledge/route_families.js +2 -2
- package/dist/logger.d.ts +1 -2
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +1 -2
- package/dist/ollama_provider.js +1 -1
- package/dist/prompts/cross-impact.d.ts +22 -0
- package/dist/prompts/cross-impact.d.ts.map +1 -0
- package/dist/prompts/cross-impact.js +75 -0
- package/dist/prompts/strategist.d.ts +25 -0
- package/dist/prompts/strategist.d.ts.map +1 -0
- package/dist/prompts/strategist.js +83 -0
- package/dist/prompts/test-designer.d.ts +33 -0
- package/dist/prompts/test-designer.d.ts.map +1 -0
- package/dist/prompts/test-designer.js +111 -0
- package/dist/provider_factory.d.ts.map +1 -1
- package/dist/provider_factory.js +6 -10
- package/dist/training/enricher.d.ts.map +1 -1
- package/dist/training/enricher.js +4 -3
- package/dist/training/validator.d.ts.map +1 -1
- package/dist/training/validator.js +2 -1
- package/package.json +1 -1
|
@@ -0,0 +1,38 @@
|
|
|
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.ImpactAnalystAgent = void 0;
|
|
6
|
+
/**
|
|
7
|
+
* Impact Analyst Agent — wraps pipeline stage1 (impact analysis) in the Agent interface.
|
|
8
|
+
*/
|
|
9
|
+
const stage1_impact_js_1 = require("../pipeline/stage1_impact.js");
|
|
10
|
+
class ImpactAnalystAgent {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.role = 'impact-analyst';
|
|
13
|
+
}
|
|
14
|
+
async execute(_task, ctx) {
|
|
15
|
+
const warnings = [];
|
|
16
|
+
if (ctx.familyGroups.length === 0) {
|
|
17
|
+
warnings.push('Impact analyst: no family groups to analyze.');
|
|
18
|
+
return { role: this.role, status: 'partial', output: [], warnings };
|
|
19
|
+
}
|
|
20
|
+
try {
|
|
21
|
+
const result = await (0, stage1_impact_js_1.runImpactStage)(ctx.familyGroups, ctx.manifest, ctx.specIndex, ctx.apiSurface, ctx.context, { provider: ctx.providerOverride });
|
|
22
|
+
ctx.impactedFlows.push(...result.decisions);
|
|
23
|
+
warnings.push(...result.warnings);
|
|
24
|
+
return {
|
|
25
|
+
role: this.role,
|
|
26
|
+
status: result.decisions.length > 0 ? 'success' : 'partial',
|
|
27
|
+
output: result.decisions,
|
|
28
|
+
warnings,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
33
|
+
warnings.push(`Impact analyst failed: ${message}`);
|
|
34
|
+
return { role: this.role, status: 'failed', output: null, warnings };
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
exports.ImpactAnalystAgent = ImpactAnalystAgent;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Agent, AgentTask, AgentResult } from '../crew/protocol.js';
|
|
2
|
+
import type { CrewContext } from '../crew/context.js';
|
|
3
|
+
import type { AgentRole } from '../crew/types.js';
|
|
4
|
+
export declare class RegressionAdvisorAgent implements Agent {
|
|
5
|
+
readonly role: AgentRole;
|
|
6
|
+
execute(_task: AgentTask, ctx: CrewContext): Promise<AgentResult>;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=regression-advisor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"regression-advisor.d.ts","sourceRoot":"","sources":["../../src/agents/regression-advisor.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAC,KAAK,EAAE,SAAS,EAAE,WAAW,EAAC,MAAM,qBAAqB,CAAC;AACvE,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,EAAC,SAAS,EAAiB,MAAM,kBAAkB,CAAC;AAUhE,qBAAa,sBAAuB,YAAW,KAAK;IAChD,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAwB;IAE1C,OAAO,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;CA0G1E"}
|
|
@@ -0,0 +1,116 @@
|
|
|
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.RegressionAdvisorAgent = void 0;
|
|
6
|
+
/**
|
|
7
|
+
* Regression Advisor Agent — identifies historically regression-prone areas
|
|
8
|
+
* using traceability data and advises the Strategist on risk scores.
|
|
9
|
+
* Mostly deterministic (traceability data analysis), with optional LLM enrichment.
|
|
10
|
+
*/
|
|
11
|
+
const feedback_js_1 = require("../agent/feedback.js");
|
|
12
|
+
const FLAKY_RISK_MULTIPLIER = 15;
|
|
13
|
+
const LOW_PRECISION_RISK_MULTIPLIER = 30;
|
|
14
|
+
const PATTERN_RISK_SCORE = 30;
|
|
15
|
+
const PATTERN_RISK_ADDITIVE = 20;
|
|
16
|
+
const MAX_RISK_SCORE = 100;
|
|
17
|
+
const MIN_PRECISION_THRESHOLD = 0.5;
|
|
18
|
+
const MIN_CALIBRATION_SAMPLES = 3;
|
|
19
|
+
class RegressionAdvisorAgent {
|
|
20
|
+
constructor() {
|
|
21
|
+
this.role = 'regression-advisor';
|
|
22
|
+
}
|
|
23
|
+
async execute(_task, ctx) {
|
|
24
|
+
const warnings = [];
|
|
25
|
+
const risks = [];
|
|
26
|
+
// Analyze calibration data for historical failure patterns
|
|
27
|
+
const calibration = (0, feedback_js_1.readCalibration)(ctx.testsRoot);
|
|
28
|
+
const flakyData = (0, feedback_js_1.readFlakyTests)(ctx.testsRoot);
|
|
29
|
+
// Build risk from flaky test data
|
|
30
|
+
if (flakyData && flakyData.tests.length > 0) {
|
|
31
|
+
const flakyByFamily = new Map();
|
|
32
|
+
for (const test of flakyData.tests) {
|
|
33
|
+
// Use subsystem field as family identifier
|
|
34
|
+
if (test.subsystem) {
|
|
35
|
+
flakyByFamily.set(test.subsystem, (flakyByFamily.get(test.subsystem) || 0) + 1);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
for (const [familyId, count] of flakyByFamily) {
|
|
39
|
+
const isImpacted = ctx.familyGroups.some((g) => g.familyId === familyId);
|
|
40
|
+
if (isImpacted) {
|
|
41
|
+
risks.push({
|
|
42
|
+
familyId,
|
|
43
|
+
filePattern: '*',
|
|
44
|
+
riskScore: Math.min(MAX_RISK_SCORE, count * FLAKY_RISK_MULTIPLIER),
|
|
45
|
+
reason: `${count} flaky test(s) historically in this family`,
|
|
46
|
+
historicalFailures: count,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// Build risk from calibration data (subsystem-level precision/recall)
|
|
52
|
+
if (calibration && calibration.bySubsystem) {
|
|
53
|
+
for (const [subsystem, metrics] of Object.entries(calibration.bySubsystem)) {
|
|
54
|
+
const isImpacted = ctx.familyGroups.some((g) => g.familyId === subsystem);
|
|
55
|
+
if (!isImpacted)
|
|
56
|
+
continue;
|
|
57
|
+
// Low precision means many false positives — the subsystem is noisy
|
|
58
|
+
if (metrics.precision < MIN_PRECISION_THRESHOLD && metrics.samples >= MIN_CALIBRATION_SAMPLES) {
|
|
59
|
+
const existing = risks.find((r) => r.familyId === subsystem);
|
|
60
|
+
const lowPrecisionScore = Math.round((1 - metrics.precision) * LOW_PRECISION_RISK_MULTIPLIER);
|
|
61
|
+
if (existing) {
|
|
62
|
+
existing.riskScore = Math.min(MAX_RISK_SCORE, existing.riskScore + lowPrecisionScore);
|
|
63
|
+
existing.reason += `; low calibration precision (${(metrics.precision * 100).toFixed(0)}%)`;
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
risks.push({
|
|
67
|
+
familyId: subsystem,
|
|
68
|
+
filePattern: '*',
|
|
69
|
+
riskScore: lowPrecisionScore,
|
|
70
|
+
reason: `Low calibration precision (${(metrics.precision * 100).toFixed(0)}%) — historically noisy subsystem`,
|
|
71
|
+
historicalFailures: metrics.samples,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// Analyze changed files for known regression-prone patterns
|
|
78
|
+
for (const group of ctx.familyGroups) {
|
|
79
|
+
const hasApiChange = group.files.some((f) => f.path.includes('/api/') || f.path.includes('/actions/') || f.path.includes('/reducers/'));
|
|
80
|
+
const hasAuthChange = group.files.some((f) => f.path.includes('auth') || f.path.includes('login') || f.path.includes('session'));
|
|
81
|
+
const hasDBChange = group.files.some((f) => f.path.includes('/store/') || f.path.includes('/model/') || f.path.includes('migration'));
|
|
82
|
+
if (hasApiChange || hasAuthChange || hasDBChange) {
|
|
83
|
+
const existing = risks.find((r) => r.familyId === group.familyId);
|
|
84
|
+
const patterns = [
|
|
85
|
+
hasApiChange && 'API changes',
|
|
86
|
+
hasAuthChange && 'auth changes',
|
|
87
|
+
hasDBChange && 'data model changes',
|
|
88
|
+
].filter(Boolean).join(', ');
|
|
89
|
+
if (existing) {
|
|
90
|
+
existing.riskScore = Math.min(MAX_RISK_SCORE, existing.riskScore + PATTERN_RISK_ADDITIVE);
|
|
91
|
+
existing.reason += `; regression-prone patterns: ${patterns}`;
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
risks.push({
|
|
95
|
+
familyId: group.familyId,
|
|
96
|
+
filePattern: group.files.map((f) => f.path).join(', '),
|
|
97
|
+
riskScore: PATTERN_RISK_SCORE,
|
|
98
|
+
reason: `Regression-prone file patterns detected: ${patterns}`,
|
|
99
|
+
historicalFailures: 0,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
ctx.regressionRisks.push(...risks);
|
|
105
|
+
if (risks.length === 0) {
|
|
106
|
+
warnings.push('Regression advisor: no historical risk data found.');
|
|
107
|
+
}
|
|
108
|
+
return {
|
|
109
|
+
role: this.role,
|
|
110
|
+
status: risks.length > 0 ? 'success' : 'partial',
|
|
111
|
+
output: risks,
|
|
112
|
+
warnings,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
exports.RegressionAdvisorAgent = RegressionAdvisorAgent;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Agent, AgentTask, AgentResult } from '../crew/protocol.js';
|
|
2
|
+
import type { CrewContext } from '../crew/context.js';
|
|
3
|
+
import type { AgentRole } from '../crew/types.js';
|
|
4
|
+
export declare class StrategistAgent implements Agent {
|
|
5
|
+
readonly role: AgentRole;
|
|
6
|
+
execute(_task: AgentTask, ctx: CrewContext): Promise<AgentResult>;
|
|
7
|
+
private buildDefaultStrategy;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=strategist.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strategist.d.ts","sourceRoot":"","sources":["../../src/agents/strategist.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAC,KAAK,EAAE,SAAS,EAAE,WAAW,EAAC,MAAM,qBAAqB,CAAC;AACvE,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,EAAC,SAAS,EAA8B,MAAM,kBAAkB,CAAC;AAS7E,qBAAa,eAAgB,YAAW,KAAK;IACzC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAgB;IAElC,OAAO,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;IA6DvE,OAAO,CAAC,oBAAoB;CAa/B"}
|
|
@@ -0,0 +1,87 @@
|
|
|
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.StrategistAgent = void 0;
|
|
6
|
+
/**
|
|
7
|
+
* Strategist Agent — designs overall test strategy from impact analysis,
|
|
8
|
+
* cross-impact data, and regression risk.
|
|
9
|
+
*/
|
|
10
|
+
const provider_js_1 = require("../crew/provider.js");
|
|
11
|
+
const strategist_js_1 = require("../prompts/strategist.js");
|
|
12
|
+
const VALID_APPROACHES = new Set(['full-test', 'smoke-test', 'skip', 'manual-review']);
|
|
13
|
+
const VALID_CATEGORIES = new Set([
|
|
14
|
+
'happy-path', 'edge-case', 'boundary', 'negative',
|
|
15
|
+
'state-transition', 'race-condition', 'permission', 'accessibility', 'performance',
|
|
16
|
+
]);
|
|
17
|
+
const VALID_RISK = new Set(['high', 'medium', 'low', 'none']);
|
|
18
|
+
class StrategistAgent {
|
|
19
|
+
constructor() {
|
|
20
|
+
this.role = 'strategist';
|
|
21
|
+
}
|
|
22
|
+
async execute(_task, ctx) {
|
|
23
|
+
const warnings = [];
|
|
24
|
+
if (ctx.impactedFlows.length === 0) {
|
|
25
|
+
warnings.push('Strategist: no impacted flows to strategize.');
|
|
26
|
+
return { role: this.role, status: 'partial', output: [], warnings };
|
|
27
|
+
}
|
|
28
|
+
const prompt = (0, strategist_js_1.buildStrategistPrompt)({
|
|
29
|
+
impactedFlows: ctx.impactedFlows,
|
|
30
|
+
crossImpacts: ctx.crossImpacts,
|
|
31
|
+
regressionRisks: ctx.regressionRisks,
|
|
32
|
+
});
|
|
33
|
+
try {
|
|
34
|
+
const provider = await (0, provider_js_1.getCrewProvider)(ctx.providerOverride);
|
|
35
|
+
const response = await provider.generateText(prompt, {
|
|
36
|
+
maxTokens: 4000,
|
|
37
|
+
temperature: 0,
|
|
38
|
+
timeout: 45000,
|
|
39
|
+
systemPrompt: 'Return only valid JSON. Do not include markdown fences unless necessary.',
|
|
40
|
+
});
|
|
41
|
+
const parsed = (0, strategist_js_1.parseStrategistResponse)(response.text);
|
|
42
|
+
if (!parsed || parsed.strategy.length === 0) {
|
|
43
|
+
warnings.push('Strategist: LLM returned no strategy.');
|
|
44
|
+
// Fall back to default strategy
|
|
45
|
+
ctx.strategyEntries.push(...this.buildDefaultStrategy(ctx));
|
|
46
|
+
return { role: this.role, status: 'partial', output: ctx.strategyEntries, warnings };
|
|
47
|
+
}
|
|
48
|
+
const entries = parsed.strategy.map((s) => ({
|
|
49
|
+
flowId: s.flowId,
|
|
50
|
+
flowName: s.flowName,
|
|
51
|
+
priority: (['P0', 'P1', 'P2'].includes(s.priority) ? s.priority : 'P2'),
|
|
52
|
+
approach: VALID_APPROACHES.has(s.approach) ? s.approach : 'full-test',
|
|
53
|
+
rationale: s.rationale || '',
|
|
54
|
+
testCategories: (s.testCategories || []).filter((c) => VALID_CATEGORIES.has(c)),
|
|
55
|
+
crossImpactRisk: VALID_RISK.has(s.crossImpactRisk) ? s.crossImpactRisk : 'none',
|
|
56
|
+
}));
|
|
57
|
+
ctx.strategyEntries.push(...entries);
|
|
58
|
+
return {
|
|
59
|
+
role: this.role,
|
|
60
|
+
status: 'success',
|
|
61
|
+
output: entries,
|
|
62
|
+
usage: provider.getUsageStats(),
|
|
63
|
+
warnings,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
68
|
+
warnings.push(`Strategist LLM failed: ${message}. Using default strategy.`);
|
|
69
|
+
ctx.strategyEntries.push(...this.buildDefaultStrategy(ctx));
|
|
70
|
+
return { role: this.role, status: 'partial', output: ctx.strategyEntries, warnings };
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
buildDefaultStrategy(ctx) {
|
|
74
|
+
return ctx.impactedFlows
|
|
75
|
+
.filter((f) => f.action !== 'cannot_determine')
|
|
76
|
+
.map((f) => ({
|
|
77
|
+
flowId: f.flowId,
|
|
78
|
+
flowName: f.flowName,
|
|
79
|
+
priority: f.priority,
|
|
80
|
+
approach: (f.action === 'create_spec' || f.action === 'add_scenarios' ? 'full-test' : 'smoke-test'),
|
|
81
|
+
rationale: 'Default strategy based on impact action.',
|
|
82
|
+
testCategories: ['happy-path', 'edge-case'],
|
|
83
|
+
crossImpactRisk: 'none',
|
|
84
|
+
}));
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
exports.StrategistAgent = StrategistAgent;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Agent, AgentTask, AgentResult } from '../crew/protocol.js';
|
|
2
|
+
import type { CrewContext } from '../crew/context.js';
|
|
3
|
+
import type { AgentRole } from '../crew/types.js';
|
|
4
|
+
export declare class TestDesignerAgent implements Agent {
|
|
5
|
+
readonly role: AgentRole;
|
|
6
|
+
execute(_task: AgentTask, ctx: CrewContext): Promise<AgentResult>;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=test-designer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-designer.d.ts","sourceRoot":"","sources":["../../src/agents/test-designer.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAC,KAAK,EAAE,SAAS,EAAE,WAAW,EAAC,MAAM,qBAAqB,CAAC;AACvE,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,EAAC,SAAS,EAAoD,MAAM,kBAAkB,CAAC;AASnG,qBAAa,iBAAkB,YAAW,KAAK;IAC3C,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAmB;IAErC,OAAO,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;CAmG1E"}
|
|
@@ -0,0 +1,106 @@
|
|
|
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.TestDesignerAgent = void 0;
|
|
6
|
+
/**
|
|
7
|
+
* Test Designer Agent — designs structured test cases across 9 categories.
|
|
8
|
+
* Takes strategist output + API surface + existing specs and produces TestDesign[].
|
|
9
|
+
*/
|
|
10
|
+
const provider_js_1 = require("../crew/provider.js");
|
|
11
|
+
const spec_index_js_1 = require("../knowledge/spec_index.js");
|
|
12
|
+
const test_designer_js_1 = require("../prompts/test-designer.js");
|
|
13
|
+
const MAX_TEST_CASES_PER_FLOW = 15;
|
|
14
|
+
const VALID_TYPES = new Set([
|
|
15
|
+
'happy-path', 'edge-case', 'boundary', 'negative',
|
|
16
|
+
'state-transition', 'race-condition', 'permission', 'accessibility', 'performance',
|
|
17
|
+
]);
|
|
18
|
+
class TestDesignerAgent {
|
|
19
|
+
constructor() {
|
|
20
|
+
this.role = 'test-designer';
|
|
21
|
+
}
|
|
22
|
+
async execute(_task, ctx) {
|
|
23
|
+
const warnings = [];
|
|
24
|
+
if (ctx.strategyEntries.length === 0) {
|
|
25
|
+
warnings.push('Test designer: no strategy entries to design tests for.');
|
|
26
|
+
return { role: this.role, status: 'partial', output: [], warnings };
|
|
27
|
+
}
|
|
28
|
+
// Only design tests for flows with full-test or smoke-test approach
|
|
29
|
+
const designable = ctx.strategyEntries.filter((s) => s.approach === 'full-test' || s.approach === 'smoke-test');
|
|
30
|
+
if (designable.length === 0) {
|
|
31
|
+
warnings.push('Test designer: all flows are skip or manual-review.');
|
|
32
|
+
return { role: this.role, status: 'partial', output: [], warnings };
|
|
33
|
+
}
|
|
34
|
+
let provider;
|
|
35
|
+
try {
|
|
36
|
+
provider = await (0, provider_js_1.getCrewProvider)(ctx.providerOverride);
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
40
|
+
warnings.push(`Test designer provider unavailable: ${message}`);
|
|
41
|
+
return { role: this.role, status: 'failed', output: [], warnings };
|
|
42
|
+
}
|
|
43
|
+
const designs = [];
|
|
44
|
+
for (const strategy of designable) {
|
|
45
|
+
const flow = ctx.impactedFlows.find((f) => f.flowId === strategy.flowId);
|
|
46
|
+
if (!flow) {
|
|
47
|
+
warnings.push(`Test designer: strategy entry '${strategy.flowId}' has no matching flow.`);
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
const familySpecs = (0, spec_index_js_1.getSpecsForFamily)(ctx.specIndex, flow.routeFamily, flow.featureId);
|
|
51
|
+
const relevantCrossImpacts = ctx.crossImpacts.filter((ci) => ci.sourceFamily === flow.routeFamily || ci.affectedFamily === flow.routeFamily);
|
|
52
|
+
const prompt = (0, test_designer_js_1.buildTestDesignerPrompt)({
|
|
53
|
+
flow,
|
|
54
|
+
strategy,
|
|
55
|
+
apiSurface: ctx.apiSurface,
|
|
56
|
+
existingSpecs: familySpecs,
|
|
57
|
+
crossImpacts: relevantCrossImpacts,
|
|
58
|
+
});
|
|
59
|
+
try {
|
|
60
|
+
const response = await provider.generateText(prompt, {
|
|
61
|
+
maxTokens: 4000,
|
|
62
|
+
temperature: 0.1,
|
|
63
|
+
timeout: 60000,
|
|
64
|
+
systemPrompt: 'Return only valid JSON. Do not include markdown fences unless necessary.',
|
|
65
|
+
});
|
|
66
|
+
const parsed = (0, test_designer_js_1.parseTestDesignerResponse)(response.text);
|
|
67
|
+
if (!parsed || parsed.testDesign.testCases.length === 0) {
|
|
68
|
+
warnings.push(`Test designer: no test cases returned for flow ${strategy.flowId}.`);
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
const validatedCases = parsed.testDesign.testCases
|
|
72
|
+
.filter((tc) => tc.name && tc.steps && tc.steps.length > 0)
|
|
73
|
+
.map((tc) => ({
|
|
74
|
+
name: tc.name,
|
|
75
|
+
type: VALID_TYPES.has(tc.type) ? tc.type : 'happy-path',
|
|
76
|
+
preconditions: Array.isArray(tc.preconditions) ? tc.preconditions : [],
|
|
77
|
+
steps: Array.isArray(tc.steps) ? tc.steps : [],
|
|
78
|
+
expectedOutcome: tc.expectedOutcome || '',
|
|
79
|
+
priority: (['P0', 'P1', 'P2'].includes(tc.priority) ? tc.priority : 'P2'),
|
|
80
|
+
rationale: tc.rationale || '',
|
|
81
|
+
}))
|
|
82
|
+
.slice(0, MAX_TEST_CASES_PER_FLOW);
|
|
83
|
+
if (validatedCases.length > 0) {
|
|
84
|
+
designs.push({
|
|
85
|
+
flowId: strategy.flowId,
|
|
86
|
+
flowName: strategy.flowName,
|
|
87
|
+
testCases: validatedCases,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
93
|
+
warnings.push(`Test designer failed for flow ${strategy.flowId}: ${message}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
ctx.testDesigns.push(...designs);
|
|
97
|
+
return {
|
|
98
|
+
role: this.role,
|
|
99
|
+
status: designs.length > 0 ? 'success' : 'partial',
|
|
100
|
+
output: designs,
|
|
101
|
+
usage: provider.getUsageStats(),
|
|
102
|
+
warnings,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
exports.TestDesignerAgent = TestDesignerAgent;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crew.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/crew.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,aAAa,CAAC;AAI5C,wBAAsB,cAAc,CAAC,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAgIpG"}
|
|
@@ -0,0 +1,137 @@
|
|
|
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.runCrewCommand = runCrewCommand;
|
|
6
|
+
/**
|
|
7
|
+
* CLI command: crew — runs multi-agent QA analysis workflows.
|
|
8
|
+
*/
|
|
9
|
+
const config_js_1 = require("../../agent/config.js");
|
|
10
|
+
const orchestrator_js_1 = require("../../crew/orchestrator.js");
|
|
11
|
+
const impact_analyst_js_1 = require("../../agents/impact-analyst.js");
|
|
12
|
+
const generator_js_1 = require("../../agents/generator.js");
|
|
13
|
+
const executor_js_1 = require("../../agents/executor.js");
|
|
14
|
+
const healer_js_1 = require("../../agents/healer.js");
|
|
15
|
+
const strategist_js_1 = require("../../agents/strategist.js");
|
|
16
|
+
const test_designer_js_1 = require("../../agents/test-designer.js");
|
|
17
|
+
const cross_impact_js_1 = require("../../agents/cross-impact.js");
|
|
18
|
+
const regression_advisor_js_1 = require("../../agents/regression-advisor.js");
|
|
19
|
+
const VALID_WORKFLOWS = ['full-qa', 'quick-check', 'design-only'];
|
|
20
|
+
async function runCrewCommand(args, autoConfig) {
|
|
21
|
+
if (!args.path && !autoConfig) {
|
|
22
|
+
console.error('Error: --path is required for crew command');
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
const { config } = (0, config_js_1.resolveConfig)(process.cwd(), autoConfig, {
|
|
26
|
+
path: args.path,
|
|
27
|
+
profile: args.profile,
|
|
28
|
+
testsRoot: args.testsRoot,
|
|
29
|
+
mode: 'impact',
|
|
30
|
+
gitSince: args.gitSince,
|
|
31
|
+
llmProvider: args.llmProvider,
|
|
32
|
+
});
|
|
33
|
+
const testsRoot = config.testsRoot || config.path;
|
|
34
|
+
const rawWorkflow = args.crewWorkflow || 'full-qa';
|
|
35
|
+
if (!VALID_WORKFLOWS.includes(rawWorkflow)) {
|
|
36
|
+
console.error(`Error: invalid workflow '${rawWorkflow}'. Valid: ${VALID_WORKFLOWS.join(', ')}`);
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
const workflowName = rawWorkflow;
|
|
40
|
+
const crewConfig = {
|
|
41
|
+
appPath: config.path,
|
|
42
|
+
testsRoot,
|
|
43
|
+
gitSince: args.gitSince || config.git.since,
|
|
44
|
+
routeFamilies: config.routeFamilies,
|
|
45
|
+
apiSurface: config.apiSurface,
|
|
46
|
+
workflow: workflowName,
|
|
47
|
+
providerOverride: args.llmProvider,
|
|
48
|
+
budgetUSD: args.budgetUSD,
|
|
49
|
+
dryRun: args.dryRun,
|
|
50
|
+
};
|
|
51
|
+
// Create orchestrator and register all agents
|
|
52
|
+
const orchestrator = new orchestrator_js_1.CrewOrchestrator();
|
|
53
|
+
orchestrator.registerAgent(new impact_analyst_js_1.ImpactAnalystAgent());
|
|
54
|
+
orchestrator.registerAgent(new generator_js_1.GeneratorAgent());
|
|
55
|
+
orchestrator.registerAgent(new executor_js_1.ExecutorAgent());
|
|
56
|
+
orchestrator.registerAgent(new healer_js_1.HealerAgent());
|
|
57
|
+
orchestrator.registerAgent(new strategist_js_1.StrategistAgent());
|
|
58
|
+
orchestrator.registerAgent(new test_designer_js_1.TestDesignerAgent());
|
|
59
|
+
orchestrator.registerAgent(new cross_impact_js_1.CrossImpactAgent());
|
|
60
|
+
orchestrator.registerAgent(new regression_advisor_js_1.RegressionAdvisorAgent());
|
|
61
|
+
let result;
|
|
62
|
+
try {
|
|
63
|
+
result = await orchestrator.run(crewConfig);
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
67
|
+
console.error(`Crew workflow failed: ${message}`);
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
const ctx = result.context;
|
|
71
|
+
// JSON output mode
|
|
72
|
+
if (args.jsonOutput) {
|
|
73
|
+
const jsonReport = {
|
|
74
|
+
workflow: workflowName,
|
|
75
|
+
changedFiles: ctx.changedFiles.length,
|
|
76
|
+
impactedFlows: ctx.impactedFlows,
|
|
77
|
+
strategyEntries: ctx.strategyEntries,
|
|
78
|
+
testDesigns: ctx.testDesigns,
|
|
79
|
+
crossImpacts: ctx.crossImpacts,
|
|
80
|
+
regressionRisks: ctx.regressionRisks,
|
|
81
|
+
findings: ctx.findings,
|
|
82
|
+
generatedSpecs: ctx.generatedSpecs.map((s) => ({ flowId: s.flowId, specPath: s.specPath, mode: s.mode, written: s.written })),
|
|
83
|
+
usage: { cost: ctx.usage.totalCost, requests: ctx.usage.requestCount, tokens: ctx.usage.totalTokens },
|
|
84
|
+
timings: result.timings,
|
|
85
|
+
warnings: result.warnings,
|
|
86
|
+
};
|
|
87
|
+
console.log(JSON.stringify(jsonReport, null, 2));
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
// Human-readable output
|
|
91
|
+
console.log(`Crew workflow: ${workflowName}`);
|
|
92
|
+
console.log(`Changed files: ${ctx.changedFiles.length}`);
|
|
93
|
+
console.log(`Impacted flows: ${ctx.impactedFlows.length}`);
|
|
94
|
+
console.log(`Strategy entries: ${ctx.strategyEntries.length}`);
|
|
95
|
+
console.log(`Test designs: ${ctx.testDesigns.length} (${ctx.testDesigns.reduce((sum, td) => sum + td.testCases.length, 0)} test cases)`);
|
|
96
|
+
console.log(`Cross-impacts: ${ctx.crossImpacts.length}`);
|
|
97
|
+
console.log(`Regression risks: ${ctx.regressionRisks.length}`);
|
|
98
|
+
console.log(`Findings: ${ctx.findings.length}`);
|
|
99
|
+
console.log(`Generated specs: ${ctx.generatedSpecs.length}`);
|
|
100
|
+
console.log(`Cost: $${ctx.usage.totalCost.toFixed(4)}`);
|
|
101
|
+
if (ctx.strategyEntries.length > 0) {
|
|
102
|
+
console.log('\nTest Strategy:');
|
|
103
|
+
for (const entry of ctx.strategyEntries) {
|
|
104
|
+
console.log(` ${entry.priority} ${entry.flowName} → ${entry.approach} [${entry.testCategories.join(', ')}]`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if (ctx.testDesigns.length > 0) {
|
|
108
|
+
console.log('\nTest Designs:');
|
|
109
|
+
for (const design of ctx.testDesigns) {
|
|
110
|
+
console.log(` ${design.flowName}: ${design.testCases.length} test cases`);
|
|
111
|
+
for (const tc of design.testCases) {
|
|
112
|
+
console.log(` [${tc.type}] ${tc.name} (${tc.priority})`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
if (ctx.crossImpacts.length > 0) {
|
|
117
|
+
console.log('\nCross-Family Impacts:');
|
|
118
|
+
for (const ci of ctx.crossImpacts) {
|
|
119
|
+
console.log(` ${ci.sourceFamily} → ${ci.affectedFamily} (${ci.riskLevel}): ${ci.sharedDependency}`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (result.timings && Object.keys(result.timings).length > 0) {
|
|
123
|
+
console.log('\nPhase timings:');
|
|
124
|
+
for (const [phase, ms] of Object.entries(result.timings)) {
|
|
125
|
+
console.log(` ${phase}: ${ms}ms`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
if (result.warnings.length > 0) {
|
|
129
|
+
console.log(`\nWarnings: ${result.warnings.length}`);
|
|
130
|
+
for (const w of result.warnings.slice(0, 10)) {
|
|
131
|
+
console.log(` - ${w}`);
|
|
132
|
+
}
|
|
133
|
+
if (result.warnings.length > 10) {
|
|
134
|
+
console.log(` ... and ${result.warnings.length - 10} more`);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse_args.d.ts","sourceRoot":"","sources":["../../src/cli/parse_args.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAU,UAAU,EAAC,MAAM,YAAY,CAAC;AAEpD,eAAO,MAAM,iBAAiB,UAA8D,CAAC;AAE7F,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAmBlF;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS,CAmBtE;
|
|
1
|
+
{"version":3,"file":"parse_args.d.ts","sourceRoot":"","sources":["../../src/cli/parse_args.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAU,UAAU,EAAC,MAAM,YAAY,CAAC;AAEpD,eAAO,MAAM,iBAAiB,UAA8D,CAAC;AAE7F,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAmBlF;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS,CAmBtE;AA+ID,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CA4EpD"}
|
package/dist/cli/parse_args.js
CHANGED
|
@@ -104,6 +104,7 @@ const FLAGS = {
|
|
|
104
104
|
'--flow-catalog': { key: 'flowCatalogPath', type: 'string' },
|
|
105
105
|
'--output': { key: 'trainOutput', type: 'string' },
|
|
106
106
|
'--server-path': { key: 'serverPath', type: 'string' },
|
|
107
|
+
'--workflow': { key: 'crewWorkflow', type: 'string' },
|
|
107
108
|
// -- number flags (with isFinite guard) --
|
|
108
109
|
'--pipeline-scenarios': { key: 'pipelineScenarios', type: 'number' },
|
|
109
110
|
'--time': { key: 'timeLimitMinutes', type: 'number' },
|
|
@@ -149,7 +150,7 @@ const COMMANDS = new Set([
|
|
|
149
150
|
'init', 'impact', 'plan', 'heal', 'suggest', 'generate',
|
|
150
151
|
'finalize-generated-tests', 'feedback',
|
|
151
152
|
'traceability-capture', 'traceability-ingest',
|
|
152
|
-
'analyze', 'llm-health', 'train',
|
|
153
|
+
'analyze', 'llm-health', 'train', 'crew',
|
|
153
154
|
]);
|
|
154
155
|
// ---------------------------------------------------------------------------
|
|
155
156
|
// Parser
|
package/dist/cli/types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AnalysisProfile, FrameworkType } from '../agent/config.js';
|
|
2
|
-
export type Command = 'init' | 'impact' | 'plan' | 'heal' | 'suggest' | 'generate' | 'finalize-generated-tests' | 'feedback' | 'traceability-capture' | 'traceability-ingest' | 'analyze' | 'llm-health' | 'train';
|
|
2
|
+
export type Command = 'init' | 'impact' | 'plan' | 'heal' | 'suggest' | 'generate' | 'finalize-generated-tests' | 'feedback' | 'traceability-capture' | 'traceability-ingest' | 'analyze' | 'llm-health' | 'train' | 'crew';
|
|
3
3
|
export interface ParsedArgs {
|
|
4
4
|
command?: Command;
|
|
5
5
|
configPath?: string;
|
|
@@ -72,6 +72,7 @@ export interface ParsedArgs {
|
|
|
72
72
|
trainOutput?: string;
|
|
73
73
|
trainYes?: boolean;
|
|
74
74
|
serverPath?: string;
|
|
75
|
+
crewWorkflow?: string;
|
|
75
76
|
verbose?: boolean;
|
|
76
77
|
jsonOutput?: boolean;
|
|
77
78
|
}
|
package/dist/cli/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/cli/types.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,eAAe,EAAE,aAAa,EAAC,MAAM,oBAAoB,CAAC;AAEvE,MAAM,MAAM,OAAO,GACf,MAAM,GACJ,QAAQ,GACR,MAAM,GACN,MAAM,GACN,SAAS,GACT,UAAU,GACV,0BAA0B,GAC1B,UAAU,GACV,sBAAsB,GACtB,qBAAqB,GACrB,SAAS,GACT,YAAY,GACZ,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/cli/types.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -17,6 +17,7 @@ const plan_js_1 = require("./cli/commands/plan.js");
|
|
|
17
17
|
const generate_js_1 = require("./cli/commands/generate.js");
|
|
18
18
|
const init_js_1 = require("./cli/commands/init.js");
|
|
19
19
|
const train_js_1 = require("./cli/commands/train.js");
|
|
20
|
+
const crew_js_1 = require("./cli/commands/crew.js");
|
|
20
21
|
async function main() {
|
|
21
22
|
const args = (0, parse_args_js_1.parseArgs)(process.argv.slice(2));
|
|
22
23
|
const autoConfig = (0, parse_args_js_1.resolveAutoConfig)(args);
|
|
@@ -61,6 +62,10 @@ async function main() {
|
|
|
61
62
|
(0, heal_js_1.runHealCommand)(args, autoConfig);
|
|
62
63
|
return;
|
|
63
64
|
}
|
|
65
|
+
if (args.command === 'crew') {
|
|
66
|
+
await (0, crew_js_1.runCrewCommand)(args, autoConfig);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
64
69
|
if (!args.path && !autoConfig) {
|
|
65
70
|
console.error('Error: --path is required (or provide a config file with path set)');
|
|
66
71
|
(0, usage_js_1.printUsage)();
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Crew Context — shared mutable state accumulated by agents across workflow phases.
|
|
3
|
+
*/
|
|
4
|
+
import type { RouteFamily, RouteFamilyManifest } from '../knowledge/route_families.js';
|
|
5
|
+
import type { ApiSurfaceCatalog } from '../knowledge/api_surface.js';
|
|
6
|
+
import type { SpecIndex } from '../knowledge/spec_index.js';
|
|
7
|
+
import type { FlowDecision } from '../validation/output_schema.js';
|
|
8
|
+
import type { ProviderUsageStats } from '../provider_interface.js';
|
|
9
|
+
import type { GeneratedSpec } from '../pipeline/stage3_generation.js';
|
|
10
|
+
import type { LoadedContext } from '../knowledge/context_loader.js';
|
|
11
|
+
import type { FamilyGroup, PreprocessResult } from '../pipeline/stage0_preprocess.js';
|
|
12
|
+
import type { AgentMessage } from './protocol.js';
|
|
13
|
+
import type { TestDesign, CrossImpact, Finding, StrategyEntry, RegressionRisk } from './types.js';
|
|
14
|
+
export interface CrewContext {
|
|
15
|
+
changedFiles: string[];
|
|
16
|
+
routeFamilies: RouteFamily[];
|
|
17
|
+
manifest: RouteFamilyManifest | null;
|
|
18
|
+
apiSurface: ApiSurfaceCatalog;
|
|
19
|
+
specIndex: SpecIndex;
|
|
20
|
+
context: LoadedContext;
|
|
21
|
+
familyGroups: FamilyGroup[];
|
|
22
|
+
preprocessResult: PreprocessResult | null;
|
|
23
|
+
appPath: string;
|
|
24
|
+
testsRoot: string;
|
|
25
|
+
gitSince: string;
|
|
26
|
+
providerOverride?: string;
|
|
27
|
+
impactedFlows: FlowDecision[];
|
|
28
|
+
strategyEntries: StrategyEntry[];
|
|
29
|
+
testDesigns: TestDesign[];
|
|
30
|
+
crossImpacts: CrossImpact[];
|
|
31
|
+
regressionRisks: RegressionRisk[];
|
|
32
|
+
findings: Finding[];
|
|
33
|
+
generatedSpecs: GeneratedSpec[];
|
|
34
|
+
usage: ProviderUsageStats;
|
|
35
|
+
messages: AgentMessage[];
|
|
36
|
+
warnings: string[];
|
|
37
|
+
}
|
|
38
|
+
export declare function createEmptyUsageStats(): ProviderUsageStats;
|
|
39
|
+
export declare function mergeUsageStats(target: ProviderUsageStats, source: ProviderUsageStats): void;
|
|
40
|
+
//# sourceMappingURL=context.d.ts.map
|