@yasserkhanorg/e2e-agents 1.7.7 → 1.8.0

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 (100) hide show
  1. package/dist/agent/git.d.ts +5 -0
  2. package/dist/agent/git.d.ts.map +1 -1
  3. package/dist/agent/git.js +13 -0
  4. package/dist/agents/coverage-evaluator.d.ts +8 -0
  5. package/dist/agents/coverage-evaluator.d.ts.map +1 -0
  6. package/dist/agents/coverage-evaluator.js +41 -0
  7. package/dist/agents/cross-impact.d.ts +13 -0
  8. package/dist/agents/cross-impact.d.ts.map +1 -0
  9. package/dist/agents/cross-impact.js +135 -0
  10. package/dist/agents/executor.d.ts +8 -0
  11. package/dist/agents/executor.d.ts.map +1 -0
  12. package/dist/agents/executor.js +70 -0
  13. package/dist/agents/explorer.d.ts +12 -0
  14. package/dist/agents/explorer.d.ts.map +1 -0
  15. package/dist/agents/explorer.js +43 -0
  16. package/dist/agents/generator.d.ts +8 -0
  17. package/dist/agents/generator.d.ts.map +1 -0
  18. package/dist/agents/generator.js +77 -0
  19. package/dist/agents/healer.d.ts +8 -0
  20. package/dist/agents/healer.d.ts.map +1 -0
  21. package/dist/agents/healer.js +31 -0
  22. package/dist/agents/impact-analyst.d.ts +8 -0
  23. package/dist/agents/impact-analyst.d.ts.map +1 -0
  24. package/dist/agents/impact-analyst.js +38 -0
  25. package/dist/agents/regression-advisor.d.ts +8 -0
  26. package/dist/agents/regression-advisor.d.ts.map +1 -0
  27. package/dist/agents/regression-advisor.js +116 -0
  28. package/dist/agents/strategist.d.ts +9 -0
  29. package/dist/agents/strategist.d.ts.map +1 -0
  30. package/dist/agents/strategist.js +87 -0
  31. package/dist/agents/test-designer.d.ts +8 -0
  32. package/dist/agents/test-designer.d.ts.map +1 -0
  33. package/dist/agents/test-designer.js +106 -0
  34. package/dist/cli/commands/crew.d.ts +3 -0
  35. package/dist/cli/commands/crew.d.ts.map +1 -0
  36. package/dist/cli/commands/crew.js +137 -0
  37. package/dist/cli/parse_args.d.ts.map +1 -1
  38. package/dist/cli/parse_args.js +2 -1
  39. package/dist/cli/types.d.ts +2 -1
  40. package/dist/cli/types.d.ts.map +1 -1
  41. package/dist/cli.js +5 -0
  42. package/dist/crew/context.d.ts +40 -0
  43. package/dist/crew/context.d.ts.map +1 -0
  44. package/dist/crew/context.js +36 -0
  45. package/dist/crew/orchestrator.d.ts +36 -0
  46. package/dist/crew/orchestrator.d.ts.map +1 -0
  47. package/dist/crew/orchestrator.js +171 -0
  48. package/dist/crew/protocol.d.ts +33 -0
  49. package/dist/crew/protocol.d.ts.map +1 -0
  50. package/dist/crew/protocol.js +4 -0
  51. package/dist/crew/provider.d.ts +3 -0
  52. package/dist/crew/provider.d.ts.map +1 -0
  53. package/dist/crew/provider.js +16 -0
  54. package/dist/crew/sanitize.d.ts +3 -0
  55. package/dist/crew/sanitize.d.ts.map +1 -0
  56. package/dist/crew/sanitize.js +31 -0
  57. package/dist/crew/types.d.ts +52 -0
  58. package/dist/crew/types.d.ts.map +1 -0
  59. package/dist/crew/types.js +4 -0
  60. package/dist/crew/workflows.d.ts +52 -0
  61. package/dist/crew/workflows.d.ts.map +1 -0
  62. package/dist/crew/workflows.js +36 -0
  63. package/dist/esm/agent/git.js +12 -0
  64. package/dist/esm/agents/coverage-evaluator.js +37 -0
  65. package/dist/esm/agents/cross-impact.js +131 -0
  66. package/dist/esm/agents/executor.js +66 -0
  67. package/dist/esm/agents/explorer.js +39 -0
  68. package/dist/esm/agents/generator.js +73 -0
  69. package/dist/esm/agents/healer.js +27 -0
  70. package/dist/esm/agents/impact-analyst.js +34 -0
  71. package/dist/esm/agents/regression-advisor.js +112 -0
  72. package/dist/esm/agents/strategist.js +83 -0
  73. package/dist/esm/agents/test-designer.js +102 -0
  74. package/dist/esm/cli/commands/crew.js +134 -0
  75. package/dist/esm/cli/parse_args.js +2 -1
  76. package/dist/esm/cli.js +5 -0
  77. package/dist/esm/crew/context.js +32 -0
  78. package/dist/esm/crew/orchestrator.js +167 -0
  79. package/dist/esm/crew/protocol.js +3 -0
  80. package/dist/esm/crew/provider.js +13 -0
  81. package/dist/esm/crew/sanitize.js +27 -0
  82. package/dist/esm/crew/types.js +3 -0
  83. package/dist/esm/crew/workflows.js +33 -0
  84. package/dist/esm/index.js +14 -0
  85. package/dist/esm/prompts/cross-impact.js +71 -0
  86. package/dist/esm/prompts/strategist.js +79 -0
  87. package/dist/esm/prompts/test-designer.js +107 -0
  88. package/dist/index.d.ts +17 -0
  89. package/dist/index.d.ts.map +1 -1
  90. package/dist/index.js +27 -1
  91. package/dist/prompts/cross-impact.d.ts +22 -0
  92. package/dist/prompts/cross-impact.d.ts.map +1 -0
  93. package/dist/prompts/cross-impact.js +75 -0
  94. package/dist/prompts/strategist.d.ts +25 -0
  95. package/dist/prompts/strategist.d.ts.map +1 -0
  96. package/dist/prompts/strategist.js +83 -0
  97. package/dist/prompts/test-designer.d.ts +33 -0
  98. package/dist/prompts/test-designer.d.ts.map +1 -0
  99. package/dist/prompts/test-designer.js +111 -0
  100. package/package.json +1 -1
@@ -0,0 +1,36 @@
1
+ import type { RouteFamilyConfig } from '../knowledge/route_families.js';
2
+ import type { ApiSurfaceConfig } from '../knowledge/api_surface.js';
3
+ import type { Agent, AgentMessage, AgentResult } from './protocol.js';
4
+ import type { CrewContext } from './context.js';
5
+ import type { AgentRole } from './types.js';
6
+ import type { WorkflowName } from './workflows.js';
7
+ export interface CrewConfig {
8
+ appPath: string;
9
+ testsRoot: string;
10
+ gitSince: string;
11
+ gitIncludeUncommitted?: boolean;
12
+ routeFamilies?: RouteFamilyConfig;
13
+ apiSurface?: ApiSurfaceConfig;
14
+ workflow?: WorkflowName;
15
+ providerOverride?: string;
16
+ budgetUSD?: number;
17
+ dryRun?: boolean;
18
+ }
19
+ export interface CrewResult {
20
+ context: CrewContext;
21
+ warnings: string[];
22
+ timings: Record<string, number>;
23
+ }
24
+ export declare class CrewOrchestrator {
25
+ private agents;
26
+ registerAgent(agent: Agent): void;
27
+ run(config: CrewConfig): Promise<CrewResult>;
28
+ dispatch(role: AgentRole, action: string, ctx: CrewContext): Promise<AgentResult>;
29
+ parallel(roles: AgentRole[], action: string, ctx: CrewContext): Promise<AgentResult[]>;
30
+ broadcast(msg: AgentMessage, ctx: CrewContext): Promise<void>;
31
+ private runBuiltInPhase;
32
+ private runParallel;
33
+ private runSequential;
34
+ private checkPhaseResults;
35
+ }
36
+ //# sourceMappingURL=orchestrator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../../src/crew/orchestrator.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,gCAAgC,CAAC;AACtE,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,6BAA6B,CAAC;AAClE,OAAO,KAAK,EAAC,KAAK,EAAE,YAAY,EAAE,WAAW,EAAY,MAAM,eAAe,CAAC;AAC/E,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,cAAc,CAAC;AAE9C,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,YAAY,CAAC;AAC1C,OAAO,KAAK,EAA6B,YAAY,EAAC,MAAM,gBAAgB,CAAC;AAG7E,MAAM,WAAW,UAAU;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,aAAa,CAAC,EAAE,iBAAiB,CAAC;IAClC,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACvB,OAAO,EAAE,WAAW,CAAC;IACrB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AAED,qBAAa,gBAAgB;IACzB,OAAO,CAAC,MAAM,CAA+B;IAE7C,aAAa,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAI3B,GAAG,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IAwE5C,QAAQ,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;IA6BjF,QAAQ,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAKtF,SAAS,CAAC,GAAG,EAAE,YAAY,EAAE,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;YAerD,eAAe;YAwBf,WAAW;YAMX,aAAa;IAS3B,OAAO,CAAC,iBAAiB;CAM5B"}
@@ -0,0 +1,171 @@
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.CrewOrchestrator = void 0;
6
+ /**
7
+ * Crew Orchestrator — executes workflow definitions by dispatching to agents.
8
+ */
9
+ const git_js_1 = require("../agent/git.js");
10
+ const stage0_preprocess_js_1 = require("../pipeline/stage0_preprocess.js");
11
+ const logger_js_1 = require("../logger.js");
12
+ const context_js_1 = require("./context.js");
13
+ const workflows_js_1 = require("./workflows.js");
14
+ class CrewOrchestrator {
15
+ constructor() {
16
+ this.agents = new Map();
17
+ }
18
+ registerAgent(agent) {
19
+ this.agents.set(agent.role, agent);
20
+ }
21
+ async run(config) {
22
+ const workflow = workflows_js_1.WORKFLOWS[config.workflow || 'full-qa'];
23
+ const timings = {};
24
+ const warnings = [];
25
+ // Step 1: Get changed files
26
+ const gitResult = (0, git_js_1.getChangedFiles)(config.appPath, config.gitSince, {
27
+ includeUncommitted: config.gitIncludeUncommitted,
28
+ });
29
+ if (gitResult.error) {
30
+ warnings.push(`Git diff warning: ${gitResult.error}`);
31
+ }
32
+ const changedFiles = gitResult.files
33
+ .map((f) => f.replace(/\\/g, '/'))
34
+ .filter((f) => !(0, git_js_1.isTestFile)(f));
35
+ if (changedFiles.length === 0) {
36
+ warnings.push('No changed application files detected.');
37
+ }
38
+ // Initialize context (will be populated during preprocess phase)
39
+ const ctx = {
40
+ changedFiles,
41
+ routeFamilies: [],
42
+ manifest: null,
43
+ apiSurface: { pageObjects: [], generatedAt: '' },
44
+ specIndex: { specs: [], indexedAt: '' },
45
+ context: { documents: [], warnings: [] },
46
+ familyGroups: [],
47
+ preprocessResult: null,
48
+ appPath: config.appPath,
49
+ testsRoot: config.testsRoot,
50
+ gitSince: config.gitSince,
51
+ providerOverride: config.providerOverride,
52
+ impactedFlows: [],
53
+ strategyEntries: [],
54
+ testDesigns: [],
55
+ crossImpacts: [],
56
+ regressionRisks: [],
57
+ findings: [],
58
+ generatedSpecs: [],
59
+ usage: (0, context_js_1.createEmptyUsageStats)(),
60
+ messages: [],
61
+ warnings,
62
+ };
63
+ // Execute each phase
64
+ for (const phase of workflow.phases) {
65
+ const timer = logger_js_1.logger.timer(`crew:${phase.name}`);
66
+ if (phase.handler === 'built-in') {
67
+ await this.runBuiltInPhase(phase.name, ctx, config);
68
+ }
69
+ else if (phase.parallel && phase.parallel.length > 0) {
70
+ await this.runParallel(phase.parallel, phase.name, ctx);
71
+ }
72
+ else if (phase.sequential && phase.sequential.length > 0) {
73
+ await this.runSequential(phase.sequential, phase.name, ctx);
74
+ }
75
+ else {
76
+ warnings.push(`Phase '${phase.name}' has no handler, parallel, or sequential agents — skipped.`);
77
+ }
78
+ timings[phase.name] = timer.end();
79
+ // Budget check
80
+ if (config.budgetUSD && ctx.usage.totalCost >= config.budgetUSD) {
81
+ warnings.push(`Budget limit reached ($${ctx.usage.totalCost.toFixed(4)} >= $${config.budgetUSD}). Stopping workflow.`);
82
+ break;
83
+ }
84
+ }
85
+ return { context: ctx, warnings, timings };
86
+ }
87
+ async dispatch(role, action, ctx) {
88
+ const agent = this.agents.get(role);
89
+ if (!agent) {
90
+ return {
91
+ role,
92
+ status: 'failed',
93
+ output: null,
94
+ warnings: [`Agent '${role}' is not registered.`],
95
+ };
96
+ }
97
+ const task = { role, action, input: null };
98
+ try {
99
+ const result = await agent.execute(task, ctx);
100
+ if (result.usage) {
101
+ (0, context_js_1.mergeUsageStats)(ctx.usage, result.usage);
102
+ }
103
+ if (result.warnings && result.warnings.length > 0) {
104
+ ctx.warnings.push(...result.warnings);
105
+ }
106
+ return result;
107
+ }
108
+ catch (error) {
109
+ const message = error instanceof Error ? error.message : String(error);
110
+ ctx.warnings.push(`Agent '${role}' failed: ${message}`);
111
+ return { role, status: 'failed', output: null, warnings: [message] };
112
+ }
113
+ }
114
+ async parallel(roles, action, ctx) {
115
+ const promises = roles.map((role) => this.dispatch(role, action, ctx));
116
+ return Promise.all(promises);
117
+ }
118
+ async broadcast(msg, ctx) {
119
+ ctx.messages.push(msg);
120
+ const promises = [];
121
+ for (const agent of this.agents.values()) {
122
+ if (agent.onMessage && agent.role !== msg.from) {
123
+ promises.push(agent.onMessage(msg).catch((err) => {
124
+ ctx.warnings.push(`Broadcast to ${agent.role} failed: ${err instanceof Error ? err.message : String(err)}`);
125
+ }));
126
+ }
127
+ }
128
+ await Promise.all(promises);
129
+ }
130
+ async runBuiltInPhase(name, ctx, config) {
131
+ if (name === 'preprocess') {
132
+ if (ctx.changedFiles.length === 0) {
133
+ return;
134
+ }
135
+ const result = (0, stage0_preprocess_js_1.preprocess)(ctx.changedFiles, {
136
+ appPath: config.appPath,
137
+ testsRoot: config.testsRoot,
138
+ routeFamilies: config.routeFamilies,
139
+ apiSurface: config.apiSurface,
140
+ });
141
+ ctx.preprocessResult = result;
142
+ ctx.manifest = result.manifest;
143
+ ctx.routeFamilies = result.manifest?.families || [];
144
+ ctx.apiSurface = result.apiSurface;
145
+ ctx.specIndex = result.specIndex;
146
+ ctx.context = result.context;
147
+ ctx.familyGroups = result.familyGroups;
148
+ ctx.warnings.push(...result.warnings);
149
+ }
150
+ }
151
+ async runParallel(roles, phaseName, ctx) {
152
+ logger_js_1.logger.info(`Crew phase '${phaseName}': running ${roles.join(', ')} in parallel`);
153
+ const results = await this.parallel(roles, phaseName, ctx);
154
+ this.checkPhaseResults(phaseName, results, ctx);
155
+ }
156
+ async runSequential(roles, phaseName, ctx) {
157
+ logger_js_1.logger.info(`Crew phase '${phaseName}': running ${roles.join(' → ')} sequentially`);
158
+ const results = [];
159
+ for (const role of roles) {
160
+ results.push(await this.dispatch(role, phaseName, ctx));
161
+ }
162
+ this.checkPhaseResults(phaseName, results, ctx);
163
+ }
164
+ checkPhaseResults(phaseName, results, ctx) {
165
+ const allFailed = results.length > 0 && results.every((r) => r.status === 'failed');
166
+ if (allFailed) {
167
+ ctx.warnings.push(`Phase '${phaseName}': all ${results.length} agent(s) failed. Downstream phases may produce empty results.`);
168
+ }
169
+ }
170
+ }
171
+ exports.CrewOrchestrator = CrewOrchestrator;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Agent Crew Protocol — core interfaces for inter-agent communication and execution.
3
+ */
4
+ import type { ProviderUsageStats } from '../provider_interface.js';
5
+ import type { AgentRole } from './types.js';
6
+ import type { CrewContext } from './context.js';
7
+ export interface AgentMessage {
8
+ id: string;
9
+ from: AgentRole;
10
+ to: AgentRole | 'broadcast';
11
+ type: 'task' | 'result' | 'escalation' | 'finding';
12
+ payload: unknown;
13
+ correlationId: string;
14
+ timestamp: number;
15
+ }
16
+ export interface AgentTask {
17
+ role: AgentRole;
18
+ action: string;
19
+ input: unknown;
20
+ }
21
+ export interface AgentResult {
22
+ role: AgentRole;
23
+ status: 'success' | 'partial' | 'failed';
24
+ output: unknown;
25
+ usage?: ProviderUsageStats;
26
+ warnings: string[];
27
+ }
28
+ export interface Agent {
29
+ role: AgentRole;
30
+ execute(task: AgentTask, ctx: CrewContext): Promise<AgentResult>;
31
+ onMessage?(msg: AgentMessage): Promise<void>;
32
+ }
33
+ //# sourceMappingURL=protocol.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../src/crew/protocol.ts"],"names":[],"mappings":"AAGA;;GAEG;AAEH,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,0BAA0B,CAAC;AACjE,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,YAAY,CAAC;AAC1C,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,cAAc,CAAC;AAE9C,MAAM,WAAW,YAAY;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,SAAS,CAAC;IAChB,EAAE,EAAE,SAAS,GAAG,WAAW,CAAC;IAC5B,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,YAAY,GAAG,SAAS,CAAC;IACnD,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,SAAS;IACtB,IAAI,EAAE,SAAS,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IACxB,IAAI,EAAE,SAAS,CAAC;IAChB,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;IACzC,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,kBAAkB,CAAC;IAC3B,QAAQ,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,KAAK;IAClB,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACjE,SAAS,CAAC,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAChD"}
@@ -0,0 +1,4 @@
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 });
@@ -0,0 +1,3 @@
1
+ import type { LLMProvider } from '../provider_interface.js';
2
+ export declare function getCrewProvider(providerOverride?: string): Promise<LLMProvider>;
3
+ //# sourceMappingURL=provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/crew/provider.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,0BAA0B,CAAC;AAE1D,wBAAsB,eAAe,CAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAKrF"}
@@ -0,0 +1,16 @@
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.getCrewProvider = getCrewProvider;
6
+ /**
7
+ * Shared provider creation for crew agents — ensures consistent provider
8
+ * instantiation and prevents usage stats fragmentation.
9
+ */
10
+ const provider_factory_js_1 = require("../provider_factory.js");
11
+ async function getCrewProvider(providerOverride) {
12
+ if (providerOverride) {
13
+ return provider_factory_js_1.LLMProviderFactory.createFromString(providerOverride);
14
+ }
15
+ return provider_factory_js_1.LLMProviderFactory.createFromEnv();
16
+ }
@@ -0,0 +1,3 @@
1
+ export declare function sanitizeForPrompt(value: string): string;
2
+ export declare function sanitizeArray(values: string[]): string[];
3
+ //# sourceMappingURL=sanitize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../../src/crew/sanitize.ts"],"names":[],"mappings":"AAqBA,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMvD;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAExD"}
@@ -0,0 +1,31 @@
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.sanitizeForPrompt = sanitizeForPrompt;
6
+ exports.sanitizeArray = sanitizeArray;
7
+ /**
8
+ * Sanitize strings before interpolating into LLM prompts.
9
+ * Strips common prompt injection patterns while preserving useful content.
10
+ */
11
+ const INJECTION_PATTERNS = [
12
+ /ignore\s+(all\s+)?previous\s+instructions/gi,
13
+ /disregard\s+(all\s+)?(above|prior|previous)/gi,
14
+ /system\s*:\s*/gi,
15
+ /\[INST\]/gi,
16
+ /<<SYS>>/gi,
17
+ /<\|im_start\|>/gi,
18
+ /\bHuman\s*:\s*/gi,
19
+ /\bAssistant\s*:\s*/gi,
20
+ ];
21
+ const MAX_FIELD_LENGTH = 2000;
22
+ function sanitizeForPrompt(value) {
23
+ let sanitized = value.slice(0, MAX_FIELD_LENGTH);
24
+ for (const pattern of INJECTION_PATTERNS) {
25
+ sanitized = sanitized.replace(pattern, '[filtered]');
26
+ }
27
+ return sanitized;
28
+ }
29
+ function sanitizeArray(values) {
30
+ return values.map((v) => sanitizeForPrompt(v));
31
+ }
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Crew data types — structured test design, cross-impact analysis, and findings.
3
+ */
4
+ export type TestCaseType = 'happy-path' | 'edge-case' | 'boundary' | 'negative' | 'state-transition' | 'race-condition' | 'permission' | 'accessibility' | 'performance';
5
+ export interface TestCase {
6
+ name: string;
7
+ type: TestCaseType;
8
+ preconditions: string[];
9
+ steps: string[];
10
+ expectedOutcome: string;
11
+ priority: 'P0' | 'P1' | 'P2';
12
+ rationale: string;
13
+ }
14
+ export interface TestDesign {
15
+ flowId: string;
16
+ flowName: string;
17
+ testCases: TestCase[];
18
+ }
19
+ export interface CrossImpact {
20
+ sourceFamily: string;
21
+ affectedFamily: string;
22
+ sharedDependency: string;
23
+ riskLevel: 'high' | 'medium' | 'low';
24
+ evidence: string;
25
+ }
26
+ export interface Finding {
27
+ id: string;
28
+ type: 'bug' | 'gap' | 'risk' | 'flaky';
29
+ severity: 'critical' | 'high' | 'medium' | 'low';
30
+ source: AgentRole;
31
+ summary: string;
32
+ details: string;
33
+ relatedFlows: string[];
34
+ }
35
+ export interface RegressionRisk {
36
+ familyId: string;
37
+ filePattern: string;
38
+ riskScore: number;
39
+ reason: string;
40
+ historicalFailures: number;
41
+ }
42
+ export interface StrategyEntry {
43
+ flowId: string;
44
+ flowName: string;
45
+ priority: 'P0' | 'P1' | 'P2';
46
+ approach: 'full-test' | 'smoke-test' | 'skip' | 'manual-review';
47
+ rationale: string;
48
+ testCategories: TestCaseType[];
49
+ crossImpactRisk: 'high' | 'medium' | 'low' | 'none';
50
+ }
51
+ export type AgentRole = 'strategist' | 'test-designer' | 'cross-impact' | 'regression-advisor' | 'impact-analyst' | 'coverage-evaluator' | 'generator' | 'executor' | 'healer' | 'explorer';
52
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/crew/types.ts"],"names":[],"mappings":"AAGA;;GAEG;AAEH,MAAM,MAAM,YAAY,GAClB,YAAY,GACZ,WAAW,GACX,UAAU,GACV,UAAU,GACV,kBAAkB,GAClB,gBAAgB,GAChB,YAAY,GACZ,eAAe,GACf,aAAa,CAAC;AAEpB,MAAM,WAAW,QAAQ;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,YAAY,CAAC;IACnB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,QAAQ,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,WAAW;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACrC,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,OAAO;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC;IACvC,QAAQ,EAAE,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACjD,MAAM,EAAE,SAAS,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,cAAc;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,kBAAkB,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,aAAa;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC7B,QAAQ,EAAE,WAAW,GAAG,YAAY,GAAG,MAAM,GAAG,eAAe,CAAC;IAChE,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,YAAY,EAAE,CAAC;IAC/B,eAAe,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;CACvD;AAED,MAAM,MAAM,SAAS,GACf,YAAY,GACZ,eAAe,GACf,cAAc,GACd,oBAAoB,GACpB,gBAAgB,GAChB,oBAAoB,GACpB,WAAW,GACX,UAAU,GACV,QAAQ,GACR,UAAU,CAAC"}
@@ -0,0 +1,4 @@
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 });
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Predefined workflow definitions — playbooks that compose agents into phases.
3
+ *
4
+ * Data flow through full-qa workflow:
5
+ *
6
+ * preprocess (built-in)
7
+ * → populates: familyGroups, routeFamilies, manifest, apiSurface, specIndex, context
8
+ *
9
+ * understand (parallel):
10
+ * impact-analyst → writes: impactedFlows
11
+ * cross-impact → writes: crossImpacts
12
+ * regression-advisor → writes: regressionRisks
13
+ *
14
+ * strategize (sequential):
15
+ * strategist → reads: impactedFlows, crossImpacts, regressionRisks
16
+ * → writes: strategyEntries
17
+ * test-designer → reads: strategyEntries, impactedFlows, crossImpacts, apiSurface, specIndex
18
+ * → writes: testDesigns
19
+ *
20
+ * execute (parallel):
21
+ * generator → reads: impactedFlows, testDesigns, apiSurface
22
+ * → writes: generatedSpecs
23
+ *
24
+ * validate (sequential):
25
+ * executor → reads: generatedSpecs, impactedFlows
26
+ * healer → reads: generatedSpecs, impactedFlows
27
+ */
28
+ import type { AgentRole } from './types.js';
29
+ export type WorkflowPhase = {
30
+ name: string;
31
+ handler: 'built-in';
32
+ parallel?: never;
33
+ sequential?: never;
34
+ } | {
35
+ name: string;
36
+ handler?: never;
37
+ parallel: AgentRole[];
38
+ sequential?: never;
39
+ } | {
40
+ name: string;
41
+ handler?: never;
42
+ parallel?: never;
43
+ sequential: AgentRole[];
44
+ };
45
+ export interface WorkflowDef {
46
+ name: string;
47
+ description: string;
48
+ phases: WorkflowPhase[];
49
+ }
50
+ export type WorkflowName = 'full-qa' | 'quick-check' | 'design-only';
51
+ export declare const WORKFLOWS: Record<WorkflowName, WorkflowDef>;
52
+ //# sourceMappingURL=workflows.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflows.d.ts","sourceRoot":"","sources":["../../src/crew/workflows.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,YAAY,CAAC;AAE1C,MAAM,MAAM,aAAa,GACnB;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,EAAE,KAAK,CAAC;IAAC,UAAU,CAAC,EAAE,KAAK,CAAA;CAAC,GACzE;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,SAAS,EAAE,CAAC;IAAC,UAAU,CAAC,EAAE,KAAK,CAAA;CAAC,GAC1E;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,EAAE,KAAK,CAAC;IAAC,UAAU,EAAE,SAAS,EAAE,CAAA;CAAC,CAAC;AAEjF,MAAM,WAAW,WAAW;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,aAAa,EAAE,CAAC;CAC3B;AAED,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,aAAa,GAAG,aAAa,CAAC;AAErE,eAAO,MAAM,SAAS,EAAE,MAAM,CAAC,YAAY,EAAE,WAAW,CA8BvD,CAAC"}
@@ -0,0 +1,36 @@
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.WORKFLOWS = void 0;
6
+ exports.WORKFLOWS = {
7
+ 'full-qa': {
8
+ name: 'full-qa',
9
+ description: 'Full multi-agent QA analysis: understand → strategize → execute → validate',
10
+ phases: [
11
+ { name: 'preprocess', handler: 'built-in' },
12
+ { name: 'understand', parallel: ['impact-analyst', 'cross-impact', 'regression-advisor'] },
13
+ { name: 'strategize', sequential: ['strategist', 'test-designer'] },
14
+ { name: 'execute', parallel: ['generator'] },
15
+ { name: 'validate', sequential: ['executor', 'healer'] },
16
+ ],
17
+ },
18
+ 'quick-check': {
19
+ name: 'quick-check',
20
+ description: 'Quick impact analysis with strategy recommendations',
21
+ phases: [
22
+ { name: 'preprocess', handler: 'built-in' },
23
+ { name: 'understand', parallel: ['impact-analyst'] },
24
+ { name: 'strategize', sequential: ['strategist'] },
25
+ ],
26
+ },
27
+ 'design-only': {
28
+ name: 'design-only',
29
+ description: 'Impact analysis through test design — no generation or execution',
30
+ phases: [
31
+ { name: 'preprocess', handler: 'built-in' },
32
+ { name: 'understand', parallel: ['impact-analyst', 'cross-impact'] },
33
+ { name: 'strategize', sequential: ['strategist', 'test-designer'] },
34
+ ],
35
+ },
36
+ };
@@ -175,6 +175,18 @@ function isCommentOnlyDiff(file, repoRoot, baseRef) {
175
175
  return content === '' || commentEntry.pattern.test(content);
176
176
  });
177
177
  }
178
+ /**
179
+ * Check if a file path is a test file (spec, test, or in test directories).
180
+ * Shared across pipeline and crew orchestrators.
181
+ */
182
+ export function isTestFile(file) {
183
+ const normalized = file.replace(/\\/g, '/');
184
+ return /\.(spec|test)\.(ts|tsx|js|jsx)$/.test(normalized) ||
185
+ /_test\.go$/.test(normalized) ||
186
+ normalized.includes('__tests__/') ||
187
+ normalized.includes('/tests/') ||
188
+ normalized.includes('/test/');
189
+ }
178
190
  export function getChangedFiles(appRoot, since, options) {
179
191
  try {
180
192
  const files = new Set();
@@ -0,0 +1,37 @@
1
+ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
2
+ // See LICENSE.txt for license information.
3
+ /**
4
+ * Coverage Evaluator Agent — wraps pipeline stage2 (coverage evaluation) in the Agent interface.
5
+ */
6
+ import { runCoverageStage } from '../pipeline/stage2_coverage.js';
7
+ export class CoverageEvaluatorAgent {
8
+ constructor() {
9
+ this.role = 'coverage-evaluator';
10
+ }
11
+ async execute(_task, ctx) {
12
+ const warnings = [];
13
+ if (ctx.impactedFlows.length === 0) {
14
+ warnings.push('Coverage evaluator: no impacted flows to evaluate.');
15
+ return { role: this.role, status: 'partial', output: [], warnings };
16
+ }
17
+ try {
18
+ const result = await runCoverageStage(ctx.impactedFlows, ctx.specIndex, ctx.context, ctx.testsRoot, { provider: ctx.providerOverride });
19
+ // Replace impacted flows with coverage-enriched versions.
20
+ // This is intentionally a full replace (not push) because coverage evaluation
21
+ // returns the same flow IDs with updated coverage fields.
22
+ ctx.impactedFlows = result.decisions;
23
+ warnings.push(...result.warnings);
24
+ return {
25
+ role: this.role,
26
+ status: 'success',
27
+ output: result.decisions,
28
+ warnings,
29
+ };
30
+ }
31
+ catch (error) {
32
+ const message = error instanceof Error ? error.message : String(error);
33
+ warnings.push(`Coverage evaluator failed: ${message}`);
34
+ return { role: this.role, status: 'failed', output: null, warnings };
35
+ }
36
+ }
37
+ }